Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2006 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, dont 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 && !$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 if ($data['crs']) { 02190 if ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output, $imagefile)) { 02191 $crsOutput = str_replace('pics/', 'pics/crs-', $output); 02192 $this->imageMagickExec($imagefile.$frame, $crsOutput, $command); 02193 $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder'); 02194 $gifCreator->init(); 02195 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] !== 0) { 02196 if (!$data['origW']) { $data['origW'] = $data[0]; } 02197 if (!$data['origH']) { $data['origH'] = $data[1]; } 02198 $ofX = intval(($data['origW'] - $data[0]) * ($data['cropH']+100)/200); 02199 $ofY = intval(($data['origH'] - $data[1]) * ($data['cropV']+100)/200); 02200 $tmpParm = Array('XY' => intval($data['origW']).','.intval($data['origH']), 02201 '10' => 'IMAGE', 02202 '10.' => array('file'=> $crsOutput, 'offset'=> $ofX.','.$ofY), 02203 ); 02204 $gifCreator->start($tmpParm, array()); 02205 $newoutput = $gifCreator->gifBuild(); 02206 if (!copy($newoutput,$output)) { 02207 $output = $newoutput; 02208 } 02209 } else { 02210 $output = $crsOutput; 02211 } 02212 } 02213 } elseif ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output,$imagefile)) { 02214 $this->imageMagickExec($imagefile.$frame,$output,$command); 02215 } 02216 if (@file_exists($output)) { 02217 $info[3] = $output; 02218 $info[2] = $newExt; 02219 if ($params) { // params could realisticly change some imagedata! 02220 $info=$this->getImageDimensions($info[3]); 02221 } 02222 if ($info[2]==$this->gifExtension && !$this->dontCompress) { 02223 t3lib_div::gif_compress($info[3],''); // Compress with IM (lzw) or GD (rle) (Workaround for the absence of lzw-compression in GD) 02224 } 02225 return $info; 02226 } 02227 } 02228 } 02229 } 02230 02238 function getImageDimensions($imageFile) { 02239 ereg('([^\.]*)$',$imageFile,$reg); 02240 if (@file_exists($imageFile) && t3lib_div::inList($this->imageFileExt,strtolower($reg[0]))) { 02241 if ($returnArr = $this->getCachedImageDimensions($imageFile)) { 02242 return $returnArr; 02243 } else { 02244 if ($temp = @getImageSize($imageFile)) { 02245 $returnArr = Array($temp[0], $temp[1], strtolower($reg[0]), $imageFile); 02246 } else { 02247 $returnArr = $this->imageMagickIdentify($imageFile); 02248 } 02249 if ($returnArr) { 02250 $this->cacheImageDimensions($returnArr); 02251 return $returnArr; 02252 } 02253 } 02254 } 02255 return false; 02256 } 02257 02266 function cacheImageDimensions($identifyResult) { 02267 global $TYPO3_DB; 02268 // Create a md5 hash of the filename 02269 if (function_exists('md5_file')) { 02270 $md5Hash = md5_file($identifyResult[3]); 02271 } else { 02272 $md5Hash = md5 (t3lib_div::getURL($identifyResult[3])); 02273 } 02274 if ($md5Hash) { 02275 $fieldArr = array ( 02276 'md5hash' => $md5Hash, 02277 'md5filename' => md5($identifyResult[3]), 02278 'tstamp' => time(), 02279 'filename' => $identifyResult[3], 02280 'imagewidth' => $identifyResult[0], 02281 'imageheight' => $identifyResult[1], 02282 ); 02283 $TYPO3_DB->exec_INSERTquery('cache_imagesizes', $fieldArr); 02284 if (!$err = $TYPO3_DB->sql_error()) { 02285 return true; 02286 } 02287 } 02288 return false; 02289 } 02290 02298 function getCachedImageDimensions($imageFile) { 02299 global $TYPO3_DB; 02300 // Create a md5 hash of the filename 02301 if(function_exists('md5_file')) { 02302 $md5Hash = md5_file($imageFile); 02303 } else { 02304 $md5Hash = md5(t3lib_div::getURL ($imageFile)); 02305 } 02306 ereg('([^\.]*)$',$imageFile,$reg); 02307 $res = $TYPO3_DB->exec_SELECTquery ('md5hash, imagewidth, imageheight', 'cache_imagesizes', 'md5filename='.$TYPO3_DB->fullQuoteStr(md5($imageFile),'cache_imagesizes')); 02308 if ($res) { 02309 if ($row = $TYPO3_DB->sql_fetch_assoc($res)) { 02310 if ($row['md5hash']!=$md5Hash) { 02311 // file has changed, delete the row 02312 $TYPO3_DB->exec_DELETEquery ('cache_imagesizes', 'md5hash='.$TYPO3_DB->fullQuoteStr($row['md5hash'],'cache_imagesizes')); 02313 } else { 02314 return (array($row['imagewidth'], $row['imageheight'], strtolower($reg[0]), $imageFile)); 02315 } 02316 } 02317 } 02318 return false; 02319 } 02320 02332 function getImageScale($info,$w,$h,$options) { 02333 if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;} 02334 02335 if (strstr($w.$h, 'c')) { 02336 $out['cropH'] = intval(substr(strstr($w, 'c'), 1)); 02337 $out['cropV'] = intval(substr(strstr($h, 'c'), 1)); 02338 $crs = true; 02339 } else { 02340 $crs = false; 02341 } 02342 $out['crs'] = $crs; 02343 02344 $w=intval($w); 02345 $h=intval($h); 02346 // if there are max-values... 02347 if ($options['maxW']) { 02348 if ($w) { // if width is given... 02349 if ($w>$options['maxW']) { 02350 $w=$options['maxW']; 02351 $max=1; // height should follow 02352 } 02353 } else { 02354 if ($info[0]>$options['maxW']) { 02355 $w=$options['maxW']; 02356 $max=1; // height should follow 02357 } 02358 } 02359 } 02360 if ($options['maxH']) { 02361 if ($h) { // if height is given... 02362 if ($h>$options['maxH']) { 02363 $h=$options['maxH']; 02364 $max=1; // height should follow 02365 } 02366 } else { 02367 if ($info[1]>$options['maxH']) { // Changed [0] to [1] 290801 02368 $h=$options['maxH']; 02369 $max=1; // height should follow 02370 } 02371 } 02372 } 02373 $out['origW']=$w; 02374 $out['origH']=$h; 02375 $out['max'] = $max; 02376 02377 if (!$this->mayScaleUp) { 02378 if ($w>$info[0]){$w=$info[0];} 02379 if ($h>$info[1]){$h=$info[1];} 02380 } 02381 if ($w || $h) { // if scaling should be performed 02382 if ($w && !$h) { 02383 $info[1] = ceil($info[1]*($w/$info[0])); 02384 $info[0] = $w; 02385 } 02386 if (!$w && $h) { 02387 $info[0] = ceil($info[0]*($h/$info[1])); 02388 $info[1] = $h; 02389 } 02390 if ($w && $h) { 02391 if ($max) { 02392 $ratio = $info[0]/$info[1]; 02393 if ($h*$ratio > $w) { 02394 $h = round($w/$ratio); 02395 } else { 02396 $w = round($h*$ratio); 02397 } 02398 } 02399 if ($crs) { 02400 $ratio = $info[0] / $info[1]; 02401 if ($h * $ratio < $w) { 02402 $h = round($w / $ratio); 02403 } else { 02404 $w = round($h * $ratio); 02405 } 02406 } 02407 $info[0] = $w; 02408 $info[1] = $h; 02409 } 02410 } 02411 $out[0]=$info[0]; 02412 $out[1]=$info[1]; 02413 // Set minimum-measures! 02414 if ($options['minW'] && $out[0]<$options['minW']) { 02415 if (($max || $crs) && $out[0]) { 02416 $out[1]= round($out[1]*$options['minW']/$out[0]); 02417 } 02418 $out[0]=$options['minW']; 02419 } 02420 if ($options['minH'] && $out[1]<$options['minH']) { 02421 if (($max || $crs) && $out[1]) { 02422 $out[0]= round($out[0]*$options['minH']/$out[1]); 02423 } 02424 $out[1]=$options['minH']; 02425 } 02426 02427 return $out; 02428 } 02429 02438 function file_exists_typo3temp_file($output,$orig='') { 02439 if ($this->enable_typo3temp_db_tracking) { 02440 if (@file_exists($output)) { // If file exists, then we return immediately 02441 return 1; 02442 } else { // If not, we look up in the cache_typo3temp_log table to see if there is a image being rendered right now. 02443 $md5Hash=md5($output); 02444 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('md5hash', 'cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log').' AND tstamp>'.(time()-30)); 02445 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // If there was a record, the image is being generated by another proces (we assume) 02446 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...) 02447 if (is_object($GLOBALS['TT'])) $GLOBALS['TT']->setTSlogMessage('typo3temp_log: Assume this file is being rendered now: '.$output); 02448 return 2; // Return 'success - 2' 02449 } 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. 02450 02451 $insertFields = array( 02452 'md5hash' => $md5Hash, 02453 'tstamp' => time(), 02454 'filename' => $output, 02455 'orig_filename' => $orig 02456 ); 02457 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log')); 02458 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_typo3temp_log', $insertFields); 02459 02460 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); 02461 return 0; 02462 } 02463 } 02464 } else { 02465 return @file_exists($output); 02466 } 02467 } 02468 02469 02470 02471 02472 02473 02474 02475 02476 02477 02478 02479 02480 02481 02482 02483 02484 02485 02486 /*********************************** 02487 * 02488 * ImageMagick API functions 02489 * 02490 ***********************************/ 02491 02499 function imageMagickIdentify($imagefile) { 02500 if (!$this->NO_IMAGE_MAGICK) { 02501 $frame = $this->noFramePrepended?'':'[0]'; 02502 $cmd = t3lib_div::imageMagickCommand('identify', $this->wrapFileName($imagefile).$frame); 02503 $returnVal = array(); 02504 exec($cmd, $returnVal); 02505 $splitstring=$returnVal[0]; 02506 $this->IM_commands[] = Array ('identify',$cmd,$returnVal[0]); 02507 if ($splitstring) { 02508 ereg('([^\.]*)$',$imagefile,$reg); 02509 $splitinfo = explode(' ', $splitstring); 02510 while (list($key,$val) = each($splitinfo)) { 02511 $temp = ''; 02512 if ($val) {$temp = explode('x', $val);} 02513 if (intval($temp[0]) && intval($temp[1])) { 02514 $dim=$temp; 02515 break; 02516 } 02517 } 02518 if ($dim[0] && $dim[1]) { 02519 return Array($dim[0], $dim[1], strtolower($reg[0]), $imagefile); 02520 } 02521 } 02522 } 02523 } 02524 02534 function imageMagickExec($input,$output,$params) { 02535 if (!$this->NO_IMAGE_MAGICK) { 02536 $cmd = t3lib_div::imageMagickCommand('convert', $params.' '.$this->wrapFileName($input).' '.$this->wrapFileName($output)); 02537 $this->IM_commands[] = array($output,$cmd); 02538 02539 $ret = exec($cmd); 02540 t3lib_div::fixPermissions($this->wrapFileName($output)); // Change the permissions of the file 02541 02542 return $ret; 02543 } 02544 } 02545 02557 function combineExec($input,$overlay,$mask,$output, $handleNegation = false) { 02558 if (!$this->NO_IMAGE_MAGICK) { 02559 $params = '-colorspace GRAY +matte'; 02560 if ($handleNegation) { 02561 if ($this->maskNegate) { 02562 $params .= ' '.$this->maskNegate; 02563 } 02564 } 02565 $theMask = $this->randomName().'.'.$this->gifExtension; 02566 $this->imageMagickExec($mask, $theMask, $params); 02567 $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 02568 $this->IM_commands[] = Array ($output,$cmd); 02569 02570 $ret = exec($cmd); 02571 t3lib_div::fixPermissions($this->wrapFileName($output)); // Change the permissions of the file 02572 02573 if (is_file($theMask)) { 02574 @unlink($theMask); 02575 } 02576 02577 return $ret; 02578 } 02579 } 02580 02588 function wrapFileName($inputName) { 02589 if (strstr($inputName,' ')) { 02590 $inputName='"'.$inputName.'"'; 02591 } 02592 return $inputName; 02593 } 02594 02595 02596 02597 02598 02599 02600 02601 02602 02603 02604 02605 02606 02607 02608 02609 02610 02611 02612 02613 02614 02615 02616 02617 /*********************************** 02618 * 02619 * Various IO functions 02620 * 02621 ***********************************/ 02622 02629 function checkFile($file) { 02630 if (@is_file($file)) { 02631 return $file; 02632 } else { 02633 return ''; 02634 } 02635 } 02636 02643 function createTempSubDir($dirName) { 02644 02645 // Checking if the this->tempPath is already prefixed with PATH_site and if not, prefix it with that constant. 02646 if (t3lib_div::isFirstPartOfStr($this->tempPath,PATH_site)) { 02647 $tmpPath = $this->tempPath; 02648 } else { 02649 $tmpPath = PATH_site.$this->tempPath; 02650 } 02651 02652 // Making the temporary filename: 02653 if (!@is_dir($tmpPath.$dirName)) { 02654 return t3lib_div::mkdir($tmpPath.$dirName); 02655 } 02656 } 02657 02665 function applyImageMagickToPHPGif(&$im, $command) { 02666 $tmpStr = $this->randomName(); 02667 $theFile = $tmpStr.'.'.$this->gifExtension; 02668 $this->ImageWrite($im, $theFile); 02669 $this->imageMagickExec($theFile,$theFile,$command); 02670 $tmpImg = $this->imageCreateFromFile($theFile); 02671 if ($tmpImg) { 02672 ImageDestroy($im); 02673 $im = $tmpImg; 02674 $this->w = imagesx($im); 02675 $this->h = imagesy($im); 02676 } 02677 if (!$this->dontUnlinkTempFiles) { 02678 unlink($theFile); 02679 } 02680 } 02681 02691 function gif_or_jpg($type,$w,$h) { 02692 if ($type=='ai' || $w*$h < $this->pixelLimitGif) { 02693 return $this->gifExtension; 02694 } else { 02695 return 'jpg'; 02696 } 02697 } 02698 02708 function output($file) { 02709 if ($file) { 02710 $reg = array(); 02711 ereg('([^\.]*)$',$file,$reg); 02712 $ext=strtolower($reg[0]); 02713 switch($ext) { 02714 case 'gif': 02715 case 'png': 02716 if ($this->ImageWrite($this->im, $file)) { 02717 // ImageMagick operations 02718 if ($this->setup['reduceColors'] || (!$this->png_truecolor && $this->truecolor)) { 02719 $reduced = $this->IMreduceColors($file, t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256)); 02720 if ($reduced) { 02721 @copy($reduced, $file); 02722 @unlink($reduced); 02723 } 02724 } 02725 t3lib_div::gif_compress($file, 'IM'); // Compress with IM! (adds extra compression, LZW from ImageMagick) (Workaround for the absence of lzw-compression in GD) 02726 } 02727 break; 02728 case 'jpg': 02729 case 'jpeg': 02730 $quality = 0; // Use the default 02731 if($this->setup['quality']) { 02732 $quality = t3lib_div::intInRange($this->setup['quality'],10,100); 02733 } 02734 if ($this->ImageWrite($this->im, $file, $quality)); 02735 break; 02736 } 02737 $GLOBALS['TEMP_IMAGES_ON_PAGE'][]=$file; 02738 } 02739 return $file; 02740 } 02741 02748 function destroy() { 02749 ImageDestroy($this->im); 02750 } 02751 02758 function imgTag ($imgInfo) { 02759 return '<img src="'.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'" border="0" alt="" />'; 02760 } 02761 02770 function ImageWrite($destImg, $theImage) { 02771 imageinterlace ($destImg,0); 02772 $ext = strtolower(substr($theImage, strrpos($theImage, '.')+1)); 02773 switch ($ext) { 02774 case 'jpg': 02775 case 'jpeg': 02776 if (function_exists('imageJpeg')) { 02777 return imageJpeg($destImg, $theImage, $this->jpegQuality); 02778 } 02779 break; 02780 case 'gif': 02781 if (function_exists('imageGif')) { 02782 if ($this->truecolor) { 02783 imagetruecolortopalette($destImg, true, 256); 02784 } 02785 return imageGif($destImg, $theImage); 02786 } 02787 break; 02788 case 'png': 02789 if (function_exists('imagePng')) { 02790 return ImagePng($destImg, $theImage); 02791 } 02792 break; 02793 } 02794 return false; // Extension invalid or write-function does not exist 02795 } 02796 02797 02798 02808 function imageGif($destImg, $theImage) { 02809 return $this->imageWrite($destImg, $theImage); 02810 } 02811 02820 function imageCreateFromGif($sourceImg) { 02821 return $this->imageCreateFromFile($sourceImg); 02822 } 02823 02831 function imageCreateFromFile($sourceImg) { 02832 $imgInf = pathinfo($sourceImg); 02833 $ext = strtolower($imgInf['extension']); 02834 02835 switch ($ext) { 02836 case 'gif': 02837 if (function_exists('imagecreatefromgif')) { 02838 return imageCreateFromGif($sourceImg); 02839 } 02840 break; 02841 case 'png': 02842 if (function_exists('imagecreatefrompng')) { 02843 return imageCreateFromPng($sourceImg); 02844 } 02845 break; 02846 case 'jpg': 02847 case 'jpeg': 02848 if (function_exists('imagecreatefromjpeg')) { 02849 return imageCreateFromJpeg($sourceImg); 02850 } 02851 break; 02852 } 02853 02854 // If non of the above: 02855 $i = @getimagesize($sourceImg); 02856 $im = $this->imagecreate($i[0],$i[1]); 02857 $Bcolor = ImageColorAllocate($im, 128,128,128); 02858 ImageFilledRectangle($im, 0, 0, $i[0], $i[1], $Bcolor); 02859 return $im; 02860 } 02861 02862 02870 function imagecreate($w, $h) { 02871 if($this->truecolor && function_exists('imagecreatetruecolor')) { 02872 return imagecreatetruecolor($w, $h); 02873 } else { 02874 return imagecreate($w, $h); 02875 } 02876 02877 } 02878 02885 function hexColor($col) { 02886 $r = dechex($col[0]); 02887 if (strlen($r)<2) { $r = '0'.$r; } 02888 $g = dechex($col[1]); 02889 if (strlen($g)<2) { $g = '0'.$g; } 02890 $b = dechex($col[2]); 02891 if (strlen($b)<2) { $b = '0'.$b; } 02892 return '#'.$r.$g.$b; 02893 } 02894 02903 function unifyColors(&$img, $colArr, $closest = false) { 02904 $retCol = -1; 02905 if (is_array($colArr) && count($colArr) && function_exists('imagepng') && function_exists('imagecreatefrompng')) { 02906 $firstCol = array_shift($colArr); 02907 $firstColArr = $this->convertColor($firstCol); 02908 if (count($colArr)>1) { 02909 $origName = $preName = $this->randomName().'.png'; 02910 $postName = $this->randomName().'.png'; 02911 $this->imageWrite($img, $preName); 02912 $firstCol = $this->hexColor($firstColArr); 02913 foreach ($colArr as $transparentColor) { 02914 $transparentColor = $this->convertColor($transparentColor); 02915 $transparentColor = $this->hexColor($transparentColor); 02916 $cmd = '-fill "'.$firstCol.'" -opaque "'.$transparentColor.'"'; 02917 $this->imageMagickExec($preName, $postName, $cmd); 02918 $preName = $postName; 02919 } 02920 $this->imageMagickExec($postName, $origName, ''); 02921 if (@is_file($origName)) { 02922 $tmpImg = $this->imageCreateFromFile($origName); 02923 } 02924 } else { 02925 $tmpImg = $img; 02926 } 02927 if ($tmpImg) { 02928 $img = $tmpImg; 02929 if ($closest) { 02930 $retCol = ImageColorClosest ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]); 02931 } else { 02932 $retCol = ImageColorExact ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]); 02933 } 02934 } 02935 // unlink files from process 02936 if (!$this->dontUnlinkTempFiles) { 02937 if ($origName) { 02938 @unlink($origName); 02939 } 02940 if ($postName) { 02941 @unlink($postName); 02942 } 02943 } 02944 } 02945 return $retCol; 02946 } 02947 02948 02949 } 02950 02951 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']) { 02952 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']); 02953 } 02954 ?>