Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 1999-2005 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 ***************************************************************/ 00148 class t3lib_stdGraphic { 00149 00150 // Internal configuration, set in init() 00151 var $combineScript = 'combine'; // The ImageMagick filename used for combining two images. This name changed during the versions. 00152 var $noFramePrepended=0; // If set, there is no frame pointer prepended to the filenames. 00153 var $GD2=0; // Set, if the GDlib used is version 2. 00154 var $imagecopyresized_fix=0; // If set, imagecopyresized will not be called directly. For GD2 (some PHP installs?) 00155 var $gifExtension = 'gif'; // This should be changed to 'png' if you want this class to read/make PNG-files instead! 00156 var $TTFLocaleConv = ''; // Used to recode input to TTF-functions for other charsets. 00157 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. 00158 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! 00159 var $webImageExt = 'gif,jpg,jpeg,png'; // Commalist of web image extensions (can be shown by a webbrowser) 00160 var $maskNegate = ''; // Will be ' -negate' if ImageMagick ver 5.2+. See init(); 00161 var $NO_IM_EFFECTS = ''; 00162 var $cmds = Array ( 00163 'jpg' => '', 00164 'jpeg' => '', 00165 'gif' => '-colors 64', 00166 'png' => '-colors 64' 00167 ); 00168 var $NO_IMAGE_MAGICK = ''; 00169 var $V5_EFFECTS = 0; 00170 var $mayScaleUp = 1; 00171 00172 // Variables for testing, alternative usage etc. 00173 var $filenamePrefix=''; // Filename prefix for images scaled in imageMagickConvert() 00174 var $imageMagickConvert_forceFileNameBody=''; // Forcing the output filename of imageMagickConvert() to this value. However after calling imageMagickConvert() it will be set blank again. 00175 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. 00176 var $dontCompress=0; // Prevents imageMagickConvert() from compressing the gif-files with t3lib_div::gif_compress() 00177 var $dontUnlinkTempFiles=0; // For debugging ONLY! 00178 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... 00179 00180 // Internal: 00181 var $IM_commands = Array(); // All ImageMagick commands executed is stored in this array for tracking. Used by the Install Tools Image section 00182 var $workArea = Array(); 00183 00184 // Constants: 00185 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. 00186 var $absPrefix = ''; // Prefix for relative paths. Used in "show_item.php" script. Is prefixed the output file name IN imageMagickConvert() 00187 var $scalecmd = '-geometry'; // ImageMagick scaling command; "-geometry" eller "-sample". Used in makeText() and imageMagickConvert() 00188 var $im5fx_blurSteps='1x2,2x2,3x2,4x3,5x3,5x4,6x4,7x5,8x5,9x5'; // Used by v5_blur() to simulate 10 continuous steps of blurring 00189 var $im5fx_sharpenSteps='1x2,2x2,3x2,2x3,3x3,4x3,3x4,4x4,4x5,5x5'; // Used by v5_sharpen() to simulate 10 continuous steps of sharpening. 00190 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 00191 var $colMap = Array ( // Array mapping HTML color names to RGB values. 00192 'aqua' => Array(0,255,255), 00193 'black' => Array(0,0,0), 00194 'blue' => Array(0,0,255), 00195 'fuchsia' => Array(255,0,255), 00196 'gray' => Array(128,128,128), 00197 'green' => Array(0,128,0), 00198 'lime' => Array(0,255,0), 00199 'maroon' => Array(128,0,0), 00200 'navy' => Array(0,0,128), 00201 'olive' => Array(128,128,0), 00202 'purple' => Array(128,0,128), 00203 'red' => Array(255,0,0), 00204 'silver' => Array(192,192,192), 00205 'teal' => Array(0,128,128), 00206 'yellow' => Array(255,255,0), 00207 'white' => Array(255,255,255) 00208 ); 00209 00210 // Charset conversion object: 00211 var $csConvObj; 00212 var $nativeCharset=''; // Is set to the native character set of the input strings. 00213 00214 00215 00216 00217 00224 function init() { 00225 $gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX']; 00226 00227 // Setting default JPG parameters: 00228 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.intval($gfxConf['im_jpg_quality']); 00229 00230 if ($gfxConf['im_combine_filename']) $this->combineScript=$gfxConf['im_combine_filename']; 00231 if ($gfxConf['im_noFramePrepended']) $this->noFramePrepended=1; 00232 00233 if ($gfxConf['gdlib_2']) { 00234 $this->GD2 = 1; 00235 $this->imagecopyresized_fix = $gfxConf['gdlib_2']==='no_imagecopyresized_fix' ? 0 : 1; 00236 } 00237 if ($gfxConf['gdlib_png']) { 00238 $this->gifExtension='png'; 00239 } 00240 if ($gfxConf['TTFLocaleConv']) { 00241 $this->TTFLocaleConv = $gfxConf['TTFLocaleConv']; 00242 } 00243 if ($gfxConf['enable_typo3temp_db_tracking']) { 00244 $this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking']; 00245 } 00246 00247 $this->imageFileExt = $gfxConf['imagefile_ext']; 00248 00249 // This should be set if ImageMagick ver. 5+ is used. 00250 if ($gfxConf['im_negate_mask']) { 00251 // Boolean. Indicates if the mask images should be inverted first. 00252 // This depends of the ImageMagick version. Below ver. 5.1 this should be false. 00253 // Above ImageMagick version 5.2+ it should be true. 00254 // Just set the flag if the masks works opposite the intension! 00255 $this->maskNegate = ' -negate'; 00256 } 00257 if ($gfxConf['im_no_effects']) { 00258 // Boolean. This is necessary if using ImageMagick 5+. 00259 // Approved version for using effects is version 4.2.9. 00260 // Effects in Imagemagick 5+ tends to render very slowly!! 00261 // - therefore must be disabled in order not to perform sharpen, blurring and such. 00262 $this->NO_IM_EFFECTS = 1; 00263 00264 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['im_jpg_quality']); 00265 } 00266 // ... but if 'im_v5effects' is set, dont care about 'im_no_effects' 00267 if ($gfxConf['im_v5effects']) { 00268 $this->NO_IM_EFFECTS = 0; 00269 $this->V5_EFFECTS = 1; 00270 00271 if ($gfxConf['im_v5effects']>0) { 00272 $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['im_jpg_quality']).$this->v5_sharpen(10); 00273 } 00274 } 00275 00276 if (!$gfxConf['im']) { 00277 $this->NO_IMAGE_MAGICK = 1; 00278 } 00279 // Secures that images are not scaled up. 00280 if ($gfxConf['im_noScaleUp']) { 00281 $this->mayScaleUp=0; 00282 } 00283 00284 if (TYPO3_MODE=='FE') { 00285 $this->csConvObj = &$GLOBALS['TSFE']->csConvObj; 00286 } elseif(is_object($GLOBALS['LANG'])) { // BE assumed: 00287 $this->csConvObj = &$GLOBALS['LANG']->csConvObj; 00288 } else { // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example. 00289 $this->csConvObj = t3lib_div::makeInstance('t3lib_cs'); 00290 } 00291 $this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']; 00292 } 00293 00294 00295 00296 00297 00298 00299 00300 00301 00302 00303 00304 00305 00306 00307 00308 00309 /************************************************* 00310 * 00311 * Layering images / "IMAGE" GIFBUILDER object 00312 * 00313 *************************************************/ 00314 00326 function maskImageOntoImage(&$im,$conf,$workArea) { 00327 if ($conf['file'] && $conf['mask']) { 00328 $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','',''); 00329 $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','',''); 00330 if ($BBimage && $BBmask) { 00331 $w = imagesx($im); 00332 $h = imagesy($im); 00333 $tmpStr = $this->randomName(); 00334 $theImage = $tmpStr.'_img.'.$this->gifExtension; 00335 $theDest = $tmpStr.'_dest.'.$this->gifExtension; 00336 $theMask = $tmpStr.'_mask.'.$this->gifExtension; 00337 $theMask2 = $tmpStr.'_mask2.'.trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']); 00338 // prepare overlay image 00339 $cpImg = $this->imageCreateFromFile($BBimage[3]); 00340 $destImg = imagecreate($w,$h); 00341 ImageColorAllocate($destImg, 0,0,0); 00342 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea); 00343 $this->ImageGif($destImg, $theImage); 00344 imageDestroy($cpImg); 00345 imageDestroy($destImg); 00346 // prepare mask image 00347 $cpImg = $this->imageCreateFromFile($BBmask[3]); 00348 $destImg = imagecreate($w,$h); 00349 ImageColorAllocate($destImg, 0,0,0); 00350 $this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea); 00351 $this->ImageGif($destImg, $theMask); 00352 imageDestroy($cpImg); 00353 imageDestroy($destImg); 00354 // treat the mask 00355 $this->imageMagickExec($theMask,$theMask2,'-colorspace GRAY'.$this->maskNegate); 00356 // mask the images 00357 $this->ImageGif($im, $theDest); 00358 00359 $this->combineExec($theDest,$theImage,$theMask2,$theDest); 00360 00361 $backIm = $this->imageCreateFromFile($theDest); // The main image is loaded again... 00362 if ($backIm) { // ... and if nothing went wrong we load it onto the old one. 00363 ImageColorTransparent($backIm,-1); 00364 $im = $backIm; 00365 } 00366 // unlink files from process 00367 if (!$this->dontUnlinkTempFiles) { 00368 unlink($theDest); 00369 unlink($theImage); 00370 unlink($theMask); 00371 unlink($theMask2); 00372 } 00373 } 00374 } 00375 } 00376 00386 function copyImageOntoImage(&$im,$conf,$workArea) { 00387 if ($conf['file']) { 00388 if ($conf['BBOX'][2]!=$this->gifExtension) { 00389 $conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','',''); 00390 $conf['file']=$conf['BBOX'][3]; 00391 } 00392 $cpImg = $this->imageCreateFromFile($conf['file']); 00393 $this->copyGifOntoGif($im,$cpImg,$conf,$workArea); 00394 imageDestroy($cpImg); 00395 } 00396 } 00397 00408 function copyGifOntoGif(&$im,$cpImg,$conf,$workArea) { 00409 $cpW = imagesx($cpImg); 00410 $cpH = imagesy($cpImg); 00411 $tile = t3lib_div::intExplode(',',$conf['tile']); 00412 $tile[0] = t3lib_div::intInRange($tile[0],1,20); 00413 $tile[1] = t3lib_div::intInRange($tile[1],1,20); 00414 $cpOff = $this->objPosition($conf,$workArea,Array($cpW*$tile[0],$cpH*$tile[1])); 00415 00416 for ($xt=0;$xt<$tile[0];$xt++) { 00417 $Xstart=$cpOff[0]+$cpW*$xt; 00418 if ($Xstart+$cpW > $workArea[0]) { // if this image is inside of the workArea, then go on 00419 // X: 00420 if ($Xstart < $workArea[0]) { 00421 $cpImgCutX = $workArea[0]-$Xstart; 00422 $Xstart = $workArea[0]; 00423 } else { 00424 $cpImgCutX = 0; 00425 } 00426 $w = $cpW-$cpImgCutX; 00427 if ($Xstart > $workArea[0]+$workArea[2]-$w) { 00428 $w = $workArea[0]+$workArea[2]-$Xstart; 00429 } 00430 if ($Xstart < $workArea[0]+$workArea[2]) { // if this image is inside of the workArea, then go on 00431 // Y: 00432 for ($yt=0;$yt<$tile[1];$yt++) { 00433 $Ystart=$cpOff[1]+$cpH*$yt; 00434 if ($Ystart+$cpH > $workArea[1]) { // if this image is inside of the workArea, then go on 00435 if ($Ystart < $workArea[1]) { 00436 $cpImgCutY = $workArea[1]-$Ystart; 00437 $Ystart = $workArea[1]; 00438 } else { 00439 $cpImgCutY = 0; 00440 } 00441 $h = $cpH-$cpImgCutY; 00442 if ($Ystart > $workArea[1]+$workArea[3]-$h) { 00443 $h = $workArea[1]+$workArea[3]-$Ystart; 00444 } 00445 if ($Ystart < $workArea[1]+$workArea[3]) { // if this image is inside of the workArea, then go on 00446 $this->imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); 00447 } 00448 } 00449 } // Y: 00450 } 00451 } 00452 } 00453 } 00454 00487 function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) { 00488 if ($this->imagecopyresized_fix) { 00489 $im_base = imagecreatetruecolor(imagesx($im), imagesy($im)); // Make true color image 00490 imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im)); // Copy the source image onto that 00491 imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); // Then copy the $cpImg onto that (the actual operation!) 00492 $im = $im_base; // Set pointer 00493 $this->makeEffect($im, Array('value'=>'colors=256')); // Reduce colors to 256 - make SURE that IM is working then! 00494 } else { 00495 imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); 00496 } 00497 } 00498 00499 00500 00501 00502 00503 00504 00505 00506 00507 00508 00509 00510 00511 00512 00513 00514 00515 00516 00517 00518 00519 00520 00521 /******************************** 00522 * 00523 * Text / "TEXT" GIFBUILDER object 00524 * 00525 ********************************/ 00526 00536 function makeText(&$im,$conf,$workArea) { 00537 // Spacing 00538 $spacing = intval($conf['spacing']); 00539 $wordSpacing = intval($conf['wordSpacing']); 00540 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2; 00541 // Position 00542 $txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']); 00543 $theText = $this->recodeString($conf['text']); 00544 00545 if ($conf['imgMap'] && is_array($conf['imgMap.'])) { 00546 $this->addToMap($this->calcTextCordsForMap($conf['BBOX'][2],$txtPos, $conf['imgMap.']), $conf['imgMap.']); 00547 } 00548 if (!$conf['hideButCreateMap']) { 00549 // Font Color: 00550 $cols=$this->convertColor($conf['fontColor']); 00551 // NiceText is calculated 00552 if (!$conf['niceText']) { 00553 // Font Color is reserved: 00554 $this->reduceColors($im,256, 200); 00555 $Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]); 00556 // antiAliasing is setup: 00557 $Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor; 00558 00559 for ($a=0; $a<$conf['iterations']; $a++) { 00560 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00561 $this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']); 00562 } else { 00563 $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']); 00564 } 00565 } 00566 } else { // NICETEXT:: 00567 // options anti_aliased and iterations is NOT available when doing this!! 00568 $w = imagesx($im); 00569 $h = imagesy($im); 00570 $tmpStr = $this->randomName(); 00571 00572 $fileMenu = $tmpStr.'_menuNT.'.$this->gifExtension; 00573 $fileColor = $tmpStr.'_colorNT.'.$this->gifExtension; 00574 $fileMask = $tmpStr.'_maskNT.'.$this->gifExtension; 00575 // Scalefactor 00576 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5); 00577 $newW = ceil($sF*imagesx($im)); 00578 $newH = ceil($sF*imagesy($im)); 00579 00580 // Make mask 00581 $maskImg = imagecreate($newW, $newH); 00582 ImageColorAllocate($maskImg, 255,255,255); 00583 $Fcolor = ImageColorAllocate($maskImg, 0,0,0); 00584 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00585 $this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF); 00586 } else { 00587 $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF); 00588 } 00589 $this->ImageGif($maskImg, $fileMask); 00590 ImageDestroy($maskImg); 00591 00592 // Downscales the mask 00593 if ($this->NO_IM_EFFECTS) { 00594 if ($this->maskNegate) { 00595 $command = trim($this->scalecmd.' '.$w.'x'.$h.'!'); // Negate 2 times makes no negate... 00596 } else { 00597 $command = trim($this->scalecmd.' '.$w.'x'.$h.'! -negate'); 00598 } 00599 } else { 00600 if ($this->maskNegate) { 00601 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after']); 00602 } else { 00603 $command = trim($conf['niceText.']['before'].' '.$this->scalecmd.' '.$w.'x'.$h.'! '.$conf['niceText.']['after'].' -negate'); 00604 } 00605 if ($conf['niceText.']['sharpen']) { 00606 if ($this->V5_EFFECTS) { 00607 $command.=$this->v5_sharpen($conf['niceText.']['sharpen']); 00608 } else { 00609 $command.=' -sharpen '.t3lib_div::intInRange($conf['niceText.']['sharpen'],1,99); 00610 } 00611 } 00612 } 00613 $this->imageMagickExec($fileMask,$fileMask,$command); 00614 00615 // Make the color-file 00616 $colorImg = imagecreate($w,$h); 00617 ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]); 00618 $this->ImageGif($colorImg, $fileColor); 00619 ImageDestroy($colorImg); 00620 00621 // The mask is applied 00622 $this->ImageGif($im, $fileMenu); // The main pictures is saved temporarily 00623 00624 $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu); 00625 00626 $backIm = $this->imageCreateFromFile($fileMenu); // The main image is loaded again... 00627 if ($backIm) { // ... and if nothing went wrong we load it onto the old one. 00628 ImageColorTransparent($backIm,-1); 00629 $im = $backIm; 00630 } 00631 00632 // Deleting temporary files; 00633 if (!$this->dontUnlinkTempFiles) { 00634 unlink($fileMenu); 00635 unlink($fileColor); 00636 unlink($fileMask); 00637 } 00638 } 00639 } 00640 } 00641 00652 function txtPosition($conf,$workArea,$BB) { 00653 $bbox = $BB[2]; 00654 $angle=intval($conf['angle'])/180*pi(); 00655 $conf['angle']=0; 00656 $straightBB = $this->calcBBox($conf); 00657 00658 // offset, align, valign, workarea 00659 $result=Array(); // [0]=x, [1]=y, [2]=w, [3]=h 00660 $result[2] = $BB[0]; 00661 $result[3] = $BB[1]; 00662 $w=$workArea[2]; 00663 $h=$workArea[3]; 00664 00665 switch($conf['align']) { 00666 case 'right': 00667 case 'center': 00668 $factor=abs(cos($angle)); 00669 $sign=(cos($angle)<0)?-1:1; 00670 $len1 = $sign*$factor*$straightBB[0]; 00671 $len2= $sign*$BB[0]; 00672 $result[0] = $w-ceil($len2*$factor+(1-$factor)*$len1); 00673 00674 $factor=abs(sin($angle)); 00675 $sign=(sin($angle)<0)?-1:1; 00676 $len1= $sign*$factor*$straightBB[0]; 00677 $len2= $sign*$BB[1]; 00678 $result[1]=ceil($len2*$factor+(1-$factor)*$len1); 00679 break; 00680 } 00681 switch($conf['align']) { 00682 case 'right': 00683 break; 00684 case 'center': 00685 $result[0] = round(($result[0])/2); 00686 $result[1] = round(($result[1])/2); 00687 break; 00688 default: 00689 $result[0]=0; 00690 $result[1]=0; 00691 break; 00692 } 00693 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset'])); 00694 $result = $this->applyOffset($result,$workArea); 00695 return $result; 00696 } 00697 00706 function calcBBox($conf) { 00707 if (!$conf['niceText']) { 00708 $sF = 1; 00709 } else { // NICETEXT:: 00710 $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5); 00711 } 00712 00713 $spacing = intval($conf['spacing']); 00714 $wordSpacing = intval($conf['wordSpacing']); 00715 $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2; 00716 00717 $spacing*=$sF; 00718 $wordSpacing*=$sF; 00719 $theText = $this->recodeString($conf['text']); 00720 00721 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF); 00722 $theBBoxInfo = $charInf; 00723 if ($conf['angle']) { 00724 $xArr = Array($charInf[0],$charInf[2],$charInf[4],$charInf[6]); 00725 $yArr = Array($charInf[1],$charInf[3],$charInf[5],$charInf[7]); 00726 $x=max($xArr)-min($xArr); 00727 $y=max($yArr)-min($yArr); 00728 } else { 00729 $x = ($charInf[2]-$charInf[0]); 00730 $y = ($charInf[1]-$charInf[7]); 00731 } 00732 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00733 $x=0; 00734 if (!$spacing && $wordSpacing) { 00735 $bits = explode(' ',$theText); 00736 while(list(,$word)=each($bits)) { 00737 $word.=' '; 00738 $wordInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $word, $conf['splitRendering.'],$sF); 00739 $wordW = ($wordInf[2]-$wordInf[0]); 00740 $x+=$wordW+$wordSpacing; 00741 } 00742 } else { 00743 $utf8Chars = $this->singleChars($theText); 00744 // For each UTF-8 char, do: 00745 foreach($utf8Chars as $char) { 00746 $charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $char, $conf['splitRendering.'],$sF); 00747 $charW = ($charInf[2]-$charInf[0]); 00748 $x+=$charW+(($char==' ')?$wordSpacing:$spacing); 00749 } 00750 } 00751 } 00752 00753 if ($sF>1) { 00754 $x = ceil($x/$sF); 00755 $y = ceil($y/$sF); 00756 if (is_array($theBBoxInfo)) { 00757 reset($theBBoxInfo); 00758 while(list($key,$val)=each($theBBoxInfo)) { 00759 $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF); 00760 } 00761 } 00762 } 00763 return Array($x,$y,$theBBoxInfo); 00764 } 00765 00775 function addToMap($cords,$conf) { 00776 $JS = $conf['noBlur'] ? '' : ' onfocus="blurLink(this);"'; 00777 00778 $this->map.='<area'. 00779 ' shape="poly"'. 00780 ' coords="'.implode(',',$cords).'"'. 00781 ' href="'.htmlspecialchars($conf['url']).'"'. 00782 ($conf['target'] ? ' target="'.htmlspecialchars($conf['target']).'"' : ''). 00783 $JS. 00784 (strlen($conf['titleText']) ? ' title="'.htmlspecialchars($conf['titleText']).'"' : ''). 00785 ' alt="'.htmlspecialchars($conf['altText']).'" />'; 00786 } 00787 00798 function calcTextCordsForMap($cords,$offset, $conf) { 00799 $pars = t3lib_div::intExplode(',',$conf['explode'].','); 00800 00801 $newCords[0] = $cords[0]+$offset[0]-$pars[0]; 00802 $newCords[1] = $cords[1]+$offset[1]+$pars[1]; 00803 $newCords[2] = $cords[2]+$offset[0]+$pars[0]; 00804 $newCords[3] = $cords[3]+$offset[1]+$pars[1]; 00805 $newCords[4] = $cords[4]+$offset[0]+$pars[0]; 00806 $newCords[5] = $cords[5]+$offset[1]-$pars[1]; 00807 $newCords[6] = $cords[6]+$offset[0]-$pars[0]; 00808 $newCords[7] = $cords[7]+$offset[1]-$pars[1]; 00809 00810 return $newCords; 00811 } 00812 00833 function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1) { 00834 00835 $spacing*=$sF; 00836 $wordSpacing*=$sF; 00837 00838 if (!$spacing && $wordSpacing) { 00839 $bits = explode(' ',$text); 00840 reset($bits); 00841 while(list(,$word)=each($bits)) { 00842 $word.=' '; 00843 $word = $word; 00844 $wordInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $word, $splitRenderingConf ,$sF); 00845 $wordW = ($wordInf[2]-$wordInf[0]); 00846 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $word, $splitRenderingConf, $sF); 00847 $x+=$wordW+$wordSpacing; 00848 } 00849 } else { 00850 $utf8Chars = $this->singleChars($text); 00851 // For each UTF-8 char, do: 00852 foreach($utf8Chars as $char) { 00853 $charInf = $this->ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $char, $splitRenderingConf, $sF); 00854 $charW = ($charInf[2]-$charInf[0]); 00855 $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $char, $splitRenderingConf, $sF); 00856 $x+=$charW+(($char==' ')?$wordSpacing:$spacing); 00857 } 00858 } 00859 } 00860 00870 function fontResize($conf) { 00871 // 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!!!! 00872 $maxWidth = intval($conf['maxWidth']); 00873 if ($maxWidth) { 00874 if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function: 00875 return $conf['fontSize']; 00876 // ################ no calc for spacing yet !!!!!! 00877 } else { 00878 do { 00879 // determine bounding box. 00880 $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($conf['text']), $conf['splitRendering.']); 00881 if ($conf['angle']< 0) { 00882 $pixelWidth = abs($bounds[4]-$bounds[0]); 00883 } elseif ($conf['angle'] > 0) { 00884 $pixelWidth = abs($bounds[2]-$bounds[6]); 00885 } else { 00886 $pixelWidth = abs($bounds[4]-$bounds[6]); 00887 } 00888 00889 // Size is fine, exit: 00890 if ($pixelWidth <= $maxWidth) { 00891 break; 00892 } else { 00893 $conf['fontSize']--; 00894 } 00895 } while ($conf['fontSize']>1); 00896 }//if spacing 00897 } 00898 return $conf['fontSize']; 00899 } 00900 00912 function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1) { 00913 00914 // Initialize: 00915 $offsetInfo = array(); 00916 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile); 00917 00918 // Traverse string parts: 00919 foreach($stringParts as $strCfg) { 00920 00921 // Calculate Bounding Box for part: 00922 $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']); 00923 00924 // Calculate offsets: 00925 if (!count($offsetInfo)) { 00926 $offsetInfo = $calc; // First run, just copy over. 00927 } else { 00928 $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']); 00929 $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']); 00930 $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']); 00931 $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']); 00932 } 00933 } 00934 00935 return $offsetInfo; 00936 } 00937 00953 function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1) { 00954 00955 // Initialize: 00956 $stringParts = $this->splitString($string,$splitRendering,$fontSize,$fontFile); 00957 $x = ceil($sF*$x); 00958 $y = ceil($sF*$y); 00959 00960 // Traverse string parts: 00961 foreach($stringParts as $i => $strCfg) { 00962 00963 // Initialize: 00964 $colorIndex = $color; 00965 00966 // Set custom color if any (only when niceText is off): 00967 if ($strCfg['color'] && $sF==1) { 00968 $cols = $this->convertColor($strCfg['color']); 00969 $colorIndex = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]); 00970 $colorIndex = $color >= 0 ? $colorIndex : -$colorIndex; 00971 } 00972 00973 // Setting xSpaceBefore 00974 if ($i) { 00975 $x+= intval($strCfg['xSpaceBefore']); 00976 $y-= intval($strCfg['ySpaceBefore']); 00977 } 00978 00979 // Render part: 00980 ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']); 00981 00982 // Calculate offset to apply: 00983 $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']); 00984 $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']); 00985 $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']); 00986 } 00987 } 00988 00998 function splitString($string,$splitRendering,$fontSize,$fontFile) { 00999 01000 // Initialize by setting the whole string and default configuration as the first entry. 01001 $result = array(); 01002 $result[] = array( 01003 'str' => $string, 01004 'fontSize' => $fontSize, 01005 'fontFile' => $fontFile 01006 ); 01007 01008 // Traverse the split-rendering configuration: 01009 // Splitting will create more entries in $result with individual configurations. 01010 if (is_array($splitRendering)) { 01011 $sKeyArray = t3lib_TStemplate::sortedKeyList($splitRendering); 01012 01013 // Traverse configured options: 01014 foreach($sKeyArray as $key) { 01015 $cfg = $splitRendering[$key.'.']; 01016 01017 // Process each type of split rendering keyword: 01018 switch((string)$splitRendering[$key]) { 01019 case 'highlightWord': 01020 if (strlen($cfg['value'])) { 01021 $newResult = array(); 01022 01023 // Traverse the current parts of the result array: 01024 foreach($result as $part) { 01025 // Explode the string value by the word value to highlight: 01026 $explodedParts = explode($cfg['value'],$part['str']); 01027 foreach($explodedParts as $c => $expValue) { 01028 if (strlen($expValue)) { 01029 $newResult[] = array_merge($part,array('str' => $expValue)); 01030 } 01031 if ($c+1 < count($explodedParts)) { 01032 $newResult[] = array( 01033 'str' => $cfg['value'], 01034 'fontSize' => $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'], 01035 'fontFile' => $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'], 01036 'color' => $cfg['color'], 01037 'xSpaceBefore' => $cfg['xSpaceBefore'], 01038 'xSpaceAfter' => $cfg['xSpaceAfter'], 01039 'ySpaceBefore' => $cfg['ySpaceBefore'], 01040 'ySpaceAfter' => $cfg['ySpaceAfter'], 01041 ); 01042 } 01043 } 01044 } 01045 01046 // Set the new result as result array: 01047 if (count($newResult)) { 01048 $result = $newResult; 01049 } 01050 } 01051 break; 01052 case 'charRange': 01053 if (strlen($cfg['value'])) { 01054 01055 // Initialize range: 01056 $ranges = t3lib_div::trimExplode(',',$cfg['value'],1); 01057 foreach($ranges as $i => $rangeDef) { 01058 $ranges[$i] = t3lib_div::intExplode('-',$ranges[$i]); 01059 if (!isset($ranges[$i][1])) $ranges[$i][1] = $ranges[$i][0]; 01060 } 01061 $newResult = array(); 01062 01063 // Traverse the current parts of the result array: 01064 foreach($result as $part) { 01065 01066 // Initialize: 01067 $currentState = -1; 01068 $bankAccum = ''; 01069 01070 // Explode the string value by the word value to highlight: 01071 $utf8Chars = $this->singleChars($part['str']); 01072 foreach($utf8Chars as $utfChar) { 01073 01074 // Find number and evaluate position: 01075 $uNumber = $this->csConvObj->utf8CharToUnumber($utfChar); 01076 $inRange = 0; 01077 foreach($ranges as $rangeDef) { 01078 if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) { 01079 $inRange = 1; 01080 break; 01081 } 01082 } 01083 if ($currentState==-1) $currentState = $inRange; // Initialize first char 01084 01085 // Switch bank: 01086 if ($inRange != $currentState && !t3lib_div::inList('32,10,13,9',$uNumber)) { 01087 01088 // Set result: 01089 if (strlen($bankAccum)) { 01090 $newResult[] = array( 01091 'str' => $bankAccum, 01092 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'], 01093 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'], 01094 'color' => $currentState ? $cfg['color'] : '', 01095 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '', 01096 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '', 01097 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '', 01098 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '', 01099 ); 01100 } 01101 01102 // Initialize new settings: 01103 $currentState = $inRange; 01104 $bankAccum = ''; 01105 } 01106 01107 // Add char to bank: 01108 $bankAccum.=$utfChar; 01109 } 01110 01111 // Set result for FINAL part: 01112 if (strlen($bankAccum)) { 01113 $newResult[] = array( 01114 'str' => $bankAccum, 01115 'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'], 01116 'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'], 01117 'color' => $currentState ? $cfg['color'] : '', 01118 'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '', 01119 'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '', 01120 'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '', 01121 'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '', 01122 ); 01123 } 01124 } 01125 01126 // Set the new result as result array: 01127 if (count($newResult)) { 01128 $result = $newResult; 01129 } 01130 } 01131 break; 01132 } 01133 } 01134 } 01135 01136 return $result; 01137 } 01138 01139 01140 01141 01142 01143 01144 01145 01146 01147 01148 01149 01150 01151 01152 01153 /********************************************* 01154 * 01155 * Other GIFBUILDER objects related to TEXT 01156 * 01157 *********************************************/ 01158 01169 function makeOutline(&$im,$conf,$workArea,$txtConf) { 01170 $thickness = intval($conf['thickness']); 01171 if ($thickness) { 01172 $txtConf['fontColor'] = $conf['color']; 01173 $outLineDist = t3lib_div::intInRange($thickness,1,2); 01174 for ($b=1;$b<=$outLineDist;$b++) { 01175 if ($b==1) { 01176 $it = 8; 01177 } else { 01178 $it = 16; 01179 } 01180 $outL = $this->circleOffset($b, $it); 01181 for ($a=0;$a<$it;$a++) { 01182 $this->makeText($im,$txtConf,$this->applyOffset($workArea,$outL[$a])); 01183 } 01184 } 01185 } 01186 } 01187 01198 function circleOffset($distance, $iterations) { 01199 $res = Array(); 01200 if ($distance && $iterations) { 01201 for ($a=0;$a<$iterations;$a++) { 01202 $yOff = round(sin(2*pi()/$iterations*($a+1))*100*$distance); 01203 if ($yOff) {$yOff = intval(ceil(abs($yOff/100))*($yOff/abs($yOff)));} 01204 $xOff = round(cos(2*pi()/$iterations*($a+1))*100*$distance); 01205 if ($xOff) {$xOff = intval(ceil(abs($xOff/100))*($xOff/abs($xOff)));} 01206 $res[$a] = Array($xOff,$yOff); 01207 } 01208 } 01209 return $res; 01210 } 01211 01222 function makeEmboss(&$im,$conf,$workArea,$txtConf) { 01223 $conf['color']=$conf['highColor']; 01224 $this->makeShadow($im,$conf,$workArea,$txtConf); 01225 $newOffset = t3lib_div::intExplode(',',$conf['offset']); 01226 $newOffset[0]*=-1; 01227 $newOffset[1]*=-1; 01228 $conf['offset']=implode(',',$newOffset); 01229 $conf['color']=$conf['lowColor']; 01230 $this->makeShadow($im,$conf,$workArea,$txtConf); 01231 } 01232 01244 function makeShadow(&$im,$conf,$workArea,$txtConf) { 01245 $workArea = $this->applyOffset($workArea,t3lib_div::intExplode(',',$conf['offset'])); 01246 $blurRate = t3lib_div::intInRange(intval($conf['blur']),0,99); 01247 01248 if (!$blurRate || $this->NO_IM_EFFECTS) { // No effects if ImageMagick ver. 5+ 01249 $txtConf['fontColor'] = $conf['color']; 01250 $this->makeText($im,$txtConf,$workArea); 01251 } else { 01252 $w = imagesx($im); 01253 $h = imagesy($im); 01254 $blurBorder= 3; // area around the blur used for cropping something 01255 $tmpStr = $this->randomName(); 01256 $fileMenu = $tmpStr.'_menu.'.$this->gifExtension; 01257 $fileColor = $tmpStr.'_color.'.$this->gifExtension; 01258 $fileMask = $tmpStr.'_mask.'.$this->gifExtension; 01259 01260 // BlurColor Image laves 01261 $blurColImg = imagecreate($w,$h); 01262 $bcols=$this->convertColor($conf['color']); 01263 ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]); 01264 $this->ImageGif($blurColImg, $fileColor); 01265 ImageDestroy($blurColImg); 01266 01267 // The mask is made: BlurTextImage 01268 $blurTextImg = imagecreate($w+$blurBorder*2,$h+$blurBorder*2); 01269 ImageColorAllocate($blurTextImg, 0,0,0); // black background 01270 $txtConf['fontColor'] = 'white'; 01271 $blurBordArr = Array($blurBorder,$blurBorder); 01272 $this->makeText($blurTextImg,$txtConf, $this->applyOffset($workArea,$blurBordArr)); 01273 $this->ImageGif($blurTextImg, $fileMask); // dump to temporary file 01274 ImageDestroy($blurTextImg); // destroy 01275 01276 01277 $command=''; 01278 $command.=$this->maskNegate; 01279 01280 if ($this->V5_EFFECTS) { 01281 $command.=$this->v5_blur($blurRate+1); 01282 } else { 01283 // Blurring of the mask 01284 $times = ceil($blurRate/10); // How many blur-commands that is executed. Min = 1; 01285 $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. 01286 $newBlurRate = t3lib_div::intInRange($newBlurRate,1,99); 01287 for ($a=0;$a<$times;$a++) { // Building blur-command 01288 $command.=' -blur '.$blurRate; 01289 } 01290 } 01291 01292 $this->imageMagickExec($fileMask,$fileMask,$command); 01293 01294 $blurTextImg_tmp = $this->imageCreateFromFile($fileMask); // the mask is loaded again 01295 if ($blurTextImg_tmp) { // if nothing went wrong we continue with the blurred mask 01296 01297 // cropping the border from the mask 01298 $blurTextImg = imagecreate($w,$h); 01299 $this->imagecopyresized($blurTextImg, $blurTextImg_tmp, 0, 0, $blurBorder, $blurBorder, $w, $h, $w, $h); 01300 ImageDestroy($blurTextImg_tmp); // Destroy the temporary mask 01301 01302 // adjust the mask 01303 $intensity = 40; 01304 if ($conf['intensity']) { 01305 $intensity = t3lib_div::intInRange($conf['intensity'],0,100); 01306 } 01307 $intensity = ceil(255-($intensity/100*255)); 01308 $this->inputLevels($blurTextImg,0,$intensity,$this->maskNegate); 01309 01310 $opacity = t3lib_div::intInRange(intval($conf['opacity']),0,100); 01311 if ($opacity && $opacity<100) { 01312 $high = ceil(255*$opacity/100); 01313 $this->outputLevels($blurTextImg,0,$high,$this->maskNegate); // reducing levels as the opacity demands 01314 } 01315 01316 $this->ImageGif($blurTextImg, $fileMask); // Dump the mask again 01317 ImageDestroy($blurTextImg); // Destroy the mask 01318 01319 // The pictures are combined 01320 $this->ImageGif($im, $fileMenu); // The main pictures is saved temporarily 01321 01322 $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu); 01323 01324 $backIm = $this->imageCreateFromFile($fileMenu); // The main image is loaded again... 01325 if ($backIm) { // ... and if nothing went wrong we load it onto the old one. 01326 ImageColorTransparent($backIm,-1); 01327 $im = $backIm; 01328 } 01329 } 01330 // Deleting temporary files; 01331 if (!$this->dontUnlinkTempFiles) { 01332 unlink($fileMenu); 01333 unlink($fileColor); 01334 unlink($fileMask); 01335 } 01336 } 01337 } 01338 01339 01340 01341 01342 01343 01344 01345 01346 01347 01348 01349 01350 01351 01352 01353 01354 01355 01356 01357 01358 01359 /**************************** 01360 * 01361 * Other GIFBUILDER objects 01362 * 01363 ****************************/ 01364 01374 function makeBox(&$im,$conf,$workArea) { 01375 $cords = t3lib_div::intExplode(',',$conf['dimensions'].',,,'); 01376 $conf['offset']=$cords[0].','.$cords[1]; 01377 $cords = $this->objPosition($conf,$workArea,Array($cords[2],$cords[3])); 01378 $cols=$this->convertColor($conf['color']); 01379 $this->reduceColors($im,256, 255); 01380 $tmpColor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]); 01381 imagefilledrectangle($im, $cords[0], $cords[1], $cords[0]+$cords[2]-1, $cords[1]+$cords[3]-1, $tmpColor); 01382 } 01383 01393 function makeEffect(&$im, $conf) { 01394 $commands = $this->IMparams($conf['value']); 01395 if ($commands) { 01396 $this->applyImageMagickToPHPGif($im, $commands); 01397 } 01398 } 01399 01408 function IMparams($setup) { 01409 if (!trim($setup)){return '';} 01410 $effects = explode('|', $setup); 01411 $commands = ''; 01412 while(list(,$val)=each($effects)) { 01413 $pairs=explode('=',$val,2); 01414 $value = trim($pairs[1]); 01415 $effect = strtolower(trim($pairs[0])); 01416 switch($effect) { 01417 case 'gamma': 01418 $commands.=' -gamma '.doubleval($value); 01419 break; 01420 case 'blur': 01421 if (!$this->NO_IM_EFFECTS) { 01422 if ($this->V5_EFFECTS) { 01423 $commands.=$this->v5_blur($value); 01424 } else { 01425 $commands.=' -blur '.t3lib_div::intInRange($value,1,99); 01426 } 01427 } 01428 break; 01429 case 'sharpen': 01430 if (!$this->NO_IM_EFFECTS) { 01431 if ($this->V5_EFFECTS) { 01432 $commands.=$this->v5_sharpen($value); 01433 } else { 01434 $commands.=' -sharpen '.t3lib_div::intInRange($value,1,99); 01435 } 01436 } 01437 break; 01438 case 'rotate': 01439 $commands.=' -rotate '.t3lib_div::intInRange($value,0,360); 01440 break; 01441 case 'solarize': 01442 $commands.=' -solarize '.t3lib_div::intInRange($value,0,99); 01443 break; 01444 case 'swirl': 01445 $commands.=' -swirl '.t3lib_div::intInRange($value,0,1000); 01446 break; 01447 case 'wave': 01448 $params = t3lib_div::intExplode(',',$value); 01449 $commands.=' -wave '.t3lib_div::intInRange($params[0],0,99).'x'.t3lib_div::intInRange($params[1],0,99); 01450 break; 01451 case 'charcoal': 01452 $commands.=' -charcoal '.t3lib_div::intInRange($value,0,100); 01453 break; 01454 case 'gray': 01455 $commands.=' -colorspace GRAY'; 01456 break; 01457 case 'edge': 01458 $commands.=' -edge '.t3lib_div::intInRange($value,0,99); 01459 break; 01460 case 'emboss': 01461 $commands.=' -emboss'; 01462 break; 01463 case 'flip': 01464 $commands.=' -flip'; 01465 break; 01466 case 'flop': 01467 $commands.=' -flop'; 01468 break; 01469 case 'colors': 01470 $commands.=' -colors '.t3lib_div::intInRange($value,2,255); 01471 break; 01472 case 'shear': 01473 $commands.=' -shear '.t3lib_div::intInRange($value,-90,90); 01474 break; 01475 case 'invert': 01476 $commands.=' -negate'; 01477 break; 01478 } 01479 } 01480 return $commands; 01481 } 01482 01491 function adjust(&$im, $conf) { 01492 $setup = $conf['value']; 01493 if (!trim($setup)){return '';} 01494 $effects = explode('|', $setup); 01495 while(list(,$val)=each($effects)) { 01496 $pairs=explode('=',$val,2); 01497 $value = trim($pairs[1]); 01498 $effect = strtolower(trim($pairs[0])); 01499 switch($effect) { 01500 case 'inputlevels': // low,high 01501 $params = t3lib_div::intExplode(',',$value); 01502 $this->inputLevels($im,$params[0],$params[1]); 01503 break; 01504 case 'outputlevels': 01505 $params = t3lib_div::intExplode(',',$value); 01506 $this->outputLevels($im,$params[0],$params[1]); 01507 break; 01508 case 'autolevels': 01509 $this->autoLevels($im); 01510 break; 01511 } 01512 } 01513 } 01514 01523 function crop(&$im,$conf) { 01524 $this->setWorkArea(''); // clears workArea to total image 01525 $cords = t3lib_div::intExplode(',',$conf['crop'].',,,'); 01526 $conf['offset']=$cords[0].','.$cords[1]; 01527 $cords = $this->objPosition($conf,$this->workArea,Array($cords[2],$cords[3])); 01528 01529 $newIm = imagecreate($cords[2],$cords[3]); 01530 $cols=$this->convertColor($conf['backColor']?$conf['backColor']:$this->setup['backColor']); 01531 ImageColorAllocate($newIm, $cols[0],$cols[1],$cols[2]); 01532 01533 $newConf = Array(); 01534 $workArea = Array(0,0,$cords[2],$cords[3]); 01535 if ($cords[0]<0) {$workArea[0]=abs($cords[0]);} else {$newConf['offset']=-$cords[0];} 01536 if ($cords[1]<0) {$workArea[1]=abs($cords[1]);} else {$newConf['offset'].=','.-$cords[1];} 01537 01538 $this->copyGifOntoGif($newIm,$im,$newConf,$workArea); 01539 $im = $newIm; 01540 $this->w = imagesx($im); 01541 $this->h = imagesy($im); 01542 $this->setWorkArea(''); // clears workArea to total image 01543 } 01544 01553 function scale(&$im,$conf) { 01554 if ($conf['width'] || $conf['height'] || $conf['params']) { 01555 $tmpStr = $this->randomName(); 01556 $theFile = $tmpStr.'.'.$this->gifExtension; 01557 $this->ImageGif($im, $theFile); 01558 $theNewFile = $this->imageMagickConvert($theFile,$this->gifExtension,$conf['width'],$conf['height'],$conf['params'],'',''); 01559 $tmpImg = $this->imageCreateFromFile($theNewFile[3]); 01560 if ($tmpImg) { 01561 ImageDestroy($im); 01562 $im = $tmpImg; 01563 $this->w = imagesx($im); 01564 $this->h = imagesy($im); 01565 $this->setWorkArea(''); // clears workArea to total image 01566 } 01567 if (!$this->dontUnlinkTempFiles) { 01568 unlink($theFile); 01569 if ($theNewFile[3] && $theNewFile[3]!=$theFile) { 01570 unlink($theNewFile[3]); 01571 } 01572 } 01573 } 01574 } 01575 01585 function setWorkArea($workArea) { 01586 $this->workArea = t3lib_div::intExplode(',',$workArea); 01587 $this->workArea = $this->applyOffset($this->workArea,$this->OFFSET); 01588 if (!$this->workArea[2]) {$this->workArea[2]=$this->w;} 01589 if (!$this->workArea[3]) {$this->workArea[3]=$this->h;} 01590 } 01591 01592 01593 01594 01595 01596 01597 01598 01599 01600 01601 01602 01603 01604 01605 01606 01607 01608 01609 01610 01611 01612 01613 01614 /************************* 01615 * 01616 * Adjustment functions 01617 * 01618 ************************/ 01619 01626 function autolevels(&$im) { 01627 $totalCols = ImageColorsTotal($im); 01628 $min=255; 01629 $max=0; 01630 for ($c=0; $c<$totalCols; $c++) { 01631 $cols = ImageColorsForIndex($im,$c); 01632 $grayArr[] = round(($cols['red']+$cols['green']+$cols['blue'])/3); 01633 } 01634 $min=min($grayArr); 01635 $max=max($grayArr); 01636 $delta = $max-$min; 01637 if ($delta) { 01638 for ($c=0; $c<$totalCols; $c++) { 01639 $cols = ImageColorsForIndex($im,$c); 01640 $cols['red'] = floor(($cols['red']-$min)/$delta*255); 01641 $cols['green'] = floor(($cols['green']-$min)/$delta*255); 01642 $cols['blue'] = floor(($cols['blue']-$min)/$delta*255); 01643 ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']); 01644 } 01645 } 01646 } 01647 01657 function outputLevels(&$im,$low,$high,$swap='') { 01658 if ($low<$high){ 01659 $low = t3lib_div::intInRange($low,0,255); 01660 $high = t3lib_div::intInRange($high,0,255); 01661 01662 if ($swap) { 01663 $temp = $low; 01664 $low = 255-$high; 01665 $high = 255-$temp; 01666 } 01667 01668 $delta = $high-$low; 01669 $totalCols = ImageColorsTotal($im); 01670 for ($c=0; $c<$totalCols; $c++) { 01671 $cols = ImageColorsForIndex($im,$c); 01672 $cols['red'] = $low+floor($cols['red']/255*$delta); 01673 $cols['green'] = $low+floor($cols['green']/255*$delta); 01674 $cols['blue'] = $low+floor($cols['blue']/255*$delta); 01675 ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']); 01676 } 01677 } 01678 } 01679 01689 function inputLevels(&$im,$low,$high,$swap='') { 01690 if ($low<$high){ 01691 $low = t3lib_div::intInRange($low,0,255); 01692 $high = t3lib_div::intInRange($high,0,255); 01693 01694 if ($swap) { 01695 $temp = $low; 01696 $low = 255-$high; 01697 $high = 255-$temp; 01698 } 01699 01700 $delta = $high-$low; 01701 $totalCols = ImageColorsTotal($im); 01702 for ($c=0; $c<$totalCols; $c++) { 01703 $cols = ImageColorsForIndex($im,$c); 01704 $cols['red'] = t3lib_div::intInRange(($cols['red']-$low)/$delta*255, 0,255); 01705 $cols['green'] = t3lib_div::intInRange(($cols['green']-$low)/$delta*255, 0,255); 01706 $cols['blue'] = t3lib_div::intInRange(($cols['blue']-$low)/$delta*255, 0,255); 01707 ImageColorSet($im,$c,$cols['red'],$cols['green'],$cols['blue']); 01708 } 01709 } 01710 } 01711 01720 function reduceColors(&$im,$limit, $cols) { 01721 if (ImageColorsTotal($im)>=$limit) { 01722 $this->makeEffect($im, Array('value'=>'colors='.$cols) ); 01723 } 01724 } 01725 01726 01727 01728 01729 01730 01731 01732 01733 01734 01735 01736 01737 01738 01739 01740 01741 01742 01743 01744 /********************************* 01745 * 01746 * GIFBUILDER Helper functions 01747 * 01748 *********************************/ 01749 01758 function prependAbsolutePath($fontFile) { 01759 $absPath = defined('PATH_typo3') ? dirname(PATH_thisScript).'/' :PATH_site; 01760 $fontFile = t3lib_div::isAbsPath($fontFile) ? $fontFile : $absPath.$fontFile; 01761 return $fontFile; 01762 } 01763 01772 function v5_sharpen($factor) { 01773 $factor = t3lib_div::intInRange(ceil($factor/10),0,10); 01774 01775 $sharpenArr=explode(',',','.$this->im5fx_sharpenSteps); 01776 $sharpenF= trim($sharpenArr[$factor]); 01777 if ($sharpenF) { 01778 $cmd = ' -sharpen '.$sharpenF; 01779 return $cmd; 01780 } 01781 } 01782 01791 function v5_blur($factor) { 01792 $factor = t3lib_div::intInRange(ceil($factor/10),0,10); 01793 01794 $blurArr=explode(',',','.$this->im5fx_blurSteps); 01795 $blurF= trim($blurArr[$factor]); 01796 if ($blurF) { 01797 $cmd=' -blur '.$blurF; 01798 return $cmd; 01799 } 01800 } 01801 01808 function randomName() { 01809 $this->createTempSubDir('temp/'); 01810 return $this->tempPath.'temp/'.md5(uniqid('')); 01811 } 01812 01821 function applyOffset($cords,$OFFSET) { 01822 $cords[0] = intval($cords[0])+intval($OFFSET[0]); 01823 $cords[1] = intval($cords[1])+intval($OFFSET[1]); 01824 return $cords; 01825 } 01826 01834 function convertColor($string) { 01835 $col=array(); 01836 $cParts = explode(':',$string,2); 01837 01838 // Finding the RGB definitions of the color: 01839 $string=$cParts[0]; 01840 if (strstr($string,'#')) { 01841 $string = ereg_replace('[^A-Fa-f0-9]*','',$string); 01842 $col[]=HexDec(substr($string,0,2)); 01843 $col[]=HexDec(substr($string,2,2)); 01844 $col[]=HexDec(substr($string,4,2)); 01845 } elseif (strstr($string,',')) { 01846 $string = ereg_replace('[^,0-9]*','',$string); 01847 $strArr = explode(',',$string); 01848 $col[]=intval($strArr[0]); 01849 $col[]=intval($strArr[1]); 01850 $col[]=intval($strArr[2]); 01851 } else { 01852 $string = strtolower(trim($string)); 01853 if ($this->colMap[$string]) { 01854 $col = $this->colMap[$string]; 01855 } else { 01856 $col = Array(0,0,0); 01857 } 01858 } 01859 // ... and possibly recalculating the value 01860 if (trim($cParts[1])) { 01861 $cParts[1]=trim($cParts[1]); 01862 if (substr($cParts[1],0,1)=='*') { 01863 $val=doubleval(substr($cParts[1],1)); 01864 $col[0]=t3lib_div::intInRange($col[0]*$val,0,255); 01865 $col[1]=t3lib_div::intInRange($col[1]*$val,0,255); 01866 $col[2]=t3lib_div::intInRange($col[2]*$val,0,255); 01867 } else { 01868 $val=intval($cParts[1]); 01869 $col[0]=t3lib_div::intInRange($col[0]+$val,0,255); 01870 $col[1]=t3lib_div::intInRange($col[1]+$val,0,255); 01871 $col[2]=t3lib_div::intInRange($col[2]+$val,0,255); 01872 } 01873 } 01874 return $col; 01875 } 01876 01884 function recodeString($string) { 01885 // Recode string to UTF-8 from $this->nativeCharset: 01886 if ($this->nativeCharset && $this->nativeCharset!='utf-8') { 01887 $string = $this->csConvObj->utf8_encode($string,$this->nativeCharset); // Convert to UTF-8 01888 } 01889 01890 // Recode string accoding to TTFLocaleConv. Depreciated. 01891 if ($this->TTFLocaleConv) { 01892 $string = recode_string($this->TTFLocaleConv,$string); 01893 } 01894 01895 return $string; 01896 } 01897 01906 function singleChars($theText,$returnUnicodeNumber=FALSE) { 01907 if ($this->nativeCharset) { 01908 return $this->csConvObj->utf8_to_numberarray($theText,1,$returnUnicodeNumber ? 0 : 1); // Get an array of separated UTF-8 chars 01909 } else { 01910 $output=array(); 01911 $c=strlen($theText); 01912 for($a=0;$a<$c;$a++) { 01913 $output[]=substr($theText,$a,1); 01914 } 01915 return $output; 01916 } 01917 } 01918 01929 function objPosition($conf,$workArea,$BB) { 01930 // offset, align, valign, workarea 01931 $result=Array(); 01932 $result[2] = $BB[0]; 01933 $result[3] = $BB[1]; 01934 $w=$workArea[2]; 01935 $h=$workArea[3]; 01936 01937 $align = explode(',',$conf['align']); 01938 $align[0] = strtolower(substr(trim($align[0]),0,1)); 01939 $align[1] = strtolower(substr(trim($align[1]),0,1)); 01940 01941 switch($align[0]) { 01942 case 'r': 01943 $result[0]=$w-$result[2]; 01944 break; 01945 case 'c': 01946 $result[0] = round(($w-$result[2])/2); 01947 break; 01948 default: 01949 $result[0] = 0; 01950 break; 01951 } 01952 switch($align[1]) { 01953 case 'b': 01954 $result[1] = $h-$result[3]; // y pos 01955 break; 01956 case 'c': 01957 $result[1] = round(($h-$result[3])/2); 01958 break; 01959 default: 01960 $result[1]=0; 01961 break; 01962 } 01963 $result = $this->applyOffset($result,t3lib_div::intExplode(',',$conf['offset'])); 01964 $result = $this->applyOffset($result,$workArea); 01965 return $result; 01966 } 01967 01968 01969 01970 01971 01972 01973 01974 01975 01976 01977 01978 01979 01980 01981 01982 01983 01984 01985 01986 01987 01988 /*********************************** 01989 * 01990 * Scaling, Dimensions of images 01991 * 01992 ***********************************/ 01993 02008 function imageMagickConvert($imagefile,$newExt='',$w='',$h='',$params='',$frame='',$options='',$mustCreate=0) { 02009 if ($this->NO_IMAGE_MAGICK) { 02010 // Returning file info right away 02011 return $this->getImageDimensions($imagefile); 02012 } 02013 02014 if($info=$this->getImageDimensions($imagefile)) { 02015 $newExt=strtolower(trim($newExt)); 02016 if (!$newExt) { // If no extension is given the original extension is used 02017 $newExt = $info[2]; 02018 } 02019 if ($newExt=='web') { 02020 if (t3lib_div::inList($this->webImageExt,$info[2])) { 02021 $newExt = $info[2]; 02022 } else { 02023 $newExt = $this->gif_or_jpg($info[2],$info[0],$info[1]); 02024 if (!$params) { 02025 $params = $this->cmds[$newExt]; 02026 } 02027 } 02028 } 02029 if (t3lib_div::inList($this->imageFileExt,$newExt)) { 02030 if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;} 02031 02032 $data = $this->getImageScale($info,$w,$h,$options); 02033 $w=$data['origW']; 02034 $h=$data['origH']; 02035 02036 // if no convertion should be performed 02037 $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.... 02038 02039 if ($wh_noscale && !$params && !$frame && $newExt==$info[2] && !$mustCreate) { 02040 $info[3] = $imagefile; 02041 return $info; 02042 } 02043 $info[0]=$data[0]; 02044 $info[1]=$data[1]; 02045 02046 $frame = $this->noFramePrepended ? '' : '['.intval($frame).']'; 02047 02048 if (!$params) { 02049 $params = $this->cmds[$newExt]; 02050 } 02051 02052 $command = $this->scalecmd.' '.$info[0].'x'.$info[1].'! '.$params.' '; 02053 02054 if ($this->alternativeOutputKey) { 02055 $theOutputName = t3lib_div::shortMD5($command.basename($imagefile).$this->alternativeOutputKey.$frame); 02056 } else { 02057 $theOutputName = t3lib_div::shortMD5($command.$imagefile.filemtime($imagefile).$frame); 02058 } 02059 if ($this->imageMagickConvert_forceFileNameBody) { 02060 $theOutputName = $this->imageMagickConvert_forceFileNameBody; 02061 $this->imageMagickConvert_forceFileNameBody=''; 02062 } 02063 02064 // Making the temporary filename: 02065 $this->createTempSubDir('pics/'); 02066 $output = $this->absPrefix.$this->tempPath.'pics/'.$this->filenamePrefix.$theOutputName.'.'.$newExt; 02067 02068 // Register temporary filename: 02069 $GLOBALS['TEMP_IMAGES_ON_PAGE'][] = $output; 02070 02071 if ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output,$imagefile)) { 02072 $this->imageMagickExec($imagefile.$frame,$output,$command); 02073 } 02074 if (@file_exists($output)) { 02075 $info[3] = $output; 02076 $info[2] = $newExt; 02077 if ($params) { // params could realisticly change som imagedata! 02078 $info=$this->getImageDimensions($info[3]); 02079 } 02080 if ($info[2]==$this->gifExtension && !$this->dontCompress) { 02081 t3lib_div::gif_compress($info[3],''); // Compress with IM (lzw) or GD (rle) (Workaround for the absence of lzw-compression in GD) 02082 } 02083 return $info; 02084 } 02085 } 02086 } 02087 } 02088 02096 function getImageDimensions($imageFile) { 02097 ereg('([^\.]*)$',$imageFile,$reg); 02098 if (@file_exists($imageFile) && t3lib_div::inList($this->imageFileExt,strtolower($reg[0]))) { 02099 if ($returnArr = $this->getCachedImageDimensions($imageFile)) { 02100 return $returnArr; 02101 } else { 02102 if ($temp = @getImageSize($imageFile)) { 02103 $returnArr = Array($temp[0], $temp[1], strtolower($reg[0]), $imageFile); 02104 } else { 02105 $returnArr = $this->imageMagickIdentify($imageFile); 02106 } 02107 if ($returnArr) { 02108 $this->cacheImageDimensions($returnArr); 02109 return $returnArr; 02110 } 02111 } 02112 } 02113 return false; 02114 } 02115 02124 function cacheImageDimensions($identifyResult) { 02125 global $TYPO3_DB; 02126 // Create a md5 hash of the filename 02127 if (function_exists('md5_file')) { 02128 $md5Hash = md5_file($identifyResult[3]); 02129 } else { 02130 $md5Hash = md5 (t3lib_div::getURL($identifyResult[3])); 02131 } 02132 if ($md5Hash) { 02133 $fieldArr = array ( 02134 'md5hash' => $md5Hash, 02135 'md5filename' => md5($identifyResult[3]), 02136 'tstamp' => time(), 02137 'filename' => $identifyResult[3], 02138 'imagewidth' => $identifyResult[0], 02139 'imageheight' => $identifyResult[1], 02140 ); 02141 $TYPO3_DB->exec_INSERTquery('cache_imagesizes', $fieldArr); 02142 if (!$err = $TYPO3_DB->sql_error()) { 02143 return true; 02144 } 02145 } 02146 return false; 02147 } 02148 02156 function getCachedImageDimensions($imageFile) { 02157 global $TYPO3_DB; 02158 // Create a md5 hash of the filename 02159 if(function_exists('md5_file')) { 02160 $md5Hash = md5_file($imageFile); 02161 } else { 02162 $md5Hash = md5(t3lib_div::getURL ($imageFile)); 02163 } 02164 ereg('([^\.]*)$',$imageFile,$reg); 02165 $res = $TYPO3_DB->exec_SELECTquery ('md5hash, imagewidth, imageheight', 'cache_imagesizes', 'md5filename='.$TYPO3_DB->fullQuoteStr(md5($imageFile),'cache_imagesizes')); 02166 if ($res) { 02167 if ($row = $TYPO3_DB->sql_fetch_assoc($res)) { 02168 if ($row['md5hash']!=$md5Hash) { 02169 // file has changed, delete the row 02170 $TYPO3_DB->exec_DELETEquery ('cache_imagesizes', 'md5hash='.$TYPO3_DB->fullQuoteStr($row['md5hash'],'cache_imagesizes')); 02171 } else { 02172 return (array($row['imagewidth'], $row['imageheight'], strtolower($reg[0]), $imageFile)); 02173 } 02174 } 02175 } 02176 return false; 02177 } 02178 02190 function getImageScale($info,$w,$h,$options) { 02191 if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;} 02192 $w=intval($w); 02193 $h=intval($h); 02194 // if there are max-values... 02195 if ($options['maxW']) { 02196 if ($w) { // if width is given... 02197 if ($w>$options['maxW']) { 02198 $w=$options['maxW']; 02199 $max=1; // height should follow 02200 } 02201 } else { 02202 if ($info[0]>$options['maxW']) { 02203 $w=$options['maxW']; 02204 $max=1; // height should follow 02205 } 02206 } 02207 } 02208 if ($options['maxH']) { 02209 if ($h) { // if height is given... 02210 if ($h>$options['maxH']) { 02211 $h=$options['maxH']; 02212 $max=1; // height should follow 02213 } 02214 } else { 02215 if ($info[1]>$options['maxH']) { // Changed [0] to [1] 290801 02216 $h=$options['maxH']; 02217 $max=1; // height should follow 02218 } 02219 } 02220 } 02221 $out['origW']=$w; 02222 $out['origH']=$h; 02223 $out['max'] = $max; 02224 02225 if (!$this->mayScaleUp) { 02226 if ($w>$info[0]){$w=$info[0];} 02227 if ($h>$info[1]){$h=$info[1];} 02228 } 02229 if ($w || $h) { // if scaling should be performed 02230 if ($w && !$h) { 02231 $info[1] = ceil($info[1]*($w/$info[0])); 02232 $info[0] = $w; 02233 } 02234 if (!$w && $h) { 02235 $info[0] = ceil($info[0]*($h/$info[1])); 02236 $info[1] = $h; 02237 } 02238 if ($w && $h) { 02239 if ($max) { 02240 $ratio = $info[0]/$info[1]; 02241 if ($h*$ratio > $w) { 02242 $h = round($w/$ratio); 02243 } else { 02244 $w = round($h*$ratio); 02245 } 02246 } 02247 $info[0] = $w; 02248 $info[1] = $h; 02249 } 02250 } 02251 $out[0]=$info[0]; 02252 $out[1]=$info[1]; 02253 // Set minimum-measures! 02254 if ($options['minW'] && $out[0]<$options['minW']) { 02255 if ($max && $out[0]) { 02256 $out[1]= round($out[1]*$options['minW']/$out[0]); 02257 } 02258 $out[0]=$options['minW']; 02259 } 02260 if ($options['minH'] && $out[1]<$options['minH']) { 02261 if ($max && $out[1]) { 02262 $out[0]= round($out[0]*$options['minH']/$out[1]); 02263 } 02264 $out[1]=$options['minH']; 02265 } 02266 02267 return $out; 02268 } 02269 02278 function file_exists_typo3temp_file($output,$orig='') { 02279 if ($this->enable_typo3temp_db_tracking) { 02280 if (@file_exists($output)) { // If file exists, then we return immediately 02281 return 1; 02282 } else { // If not, we look up in the cache_typo3temp_log table to see if there is a image being rendered right now. 02283 $md5Hash=md5($output); 02284 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('md5hash', 'cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log').' AND tstamp>'.(time()-30)); 02285 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // If there was a record, the image is being generated by another proces (we assume) 02286 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...) 02287 if (is_object($GLOBALS['TT'])) $GLOBALS['TT']->setTSlogMessage('typo3temp_log: Assume this file is being rendered now: '.$output); 02288 return 2; // Return 'success - 2' 02289 } 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. 02290 02291 $insertFields = array( 02292 'md5hash' => $md5Hash, 02293 'tstamp' => time(), 02294 'filename' => $output, 02295 'orig_filename' => $orig 02296 ); 02297 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log')); 02298 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_typo3temp_log', $insertFields); 02299 02300 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); 02301 return 0; 02302 } 02303 } 02304 } else { 02305 return @file_exists($output); 02306 } 02307 } 02308 02309 02310 02311 02312 02313 02314 02315 02316 02317 02318 02319 02320 02321 02322 02323 02324 02325 02326 /*********************************** 02327 * 02328 * ImageMagick API functions 02329 * 02330 ***********************************/ 02331 02339 function imageMagickIdentify($imagefile) { 02340 if (!$this->NO_IMAGE_MAGICK) { 02341 $frame = $this->noFramePrepended?'':'[0]'; 02342 $cmd = t3lib_div::imageMagickCommand('identify', $this->wrapFileName($imagefile).$frame); 02343 exec($cmd, $returnVal); 02344 $splitstring=$returnVal[0]; 02345 $this->IM_commands[] = Array ('identify',$cmd,$returnVal[0]); 02346 if ($splitstring) { 02347 ereg('([^\.]*)$',$imagefile,$reg); 02348 $splitinfo = explode(' ', $splitstring); 02349 while (list($key,$val) = each($splitinfo)) { 02350 $temp = ''; 02351 if ($val) {$temp = explode('x', $val);} 02352 if (intval($temp[0]) && intval($temp[1])) { 02353 $dim=$temp; 02354 break; 02355 } 02356 } 02357 if ($dim[0] && $dim[1]) { 02358 return Array($dim[0], $dim[1], strtolower($reg[0]), $imagefile); 02359 } 02360 } 02361 } 02362 } 02363 02373 function imageMagickExec($input,$output,$params) { 02374 if (!$this->NO_IMAGE_MAGICK) { 02375 $cmd = t3lib_div::imageMagickCommand('convert', $params.' '.$this->wrapFileName($input).' '.$this->wrapFileName($output)); 02376 $this->IM_commands[] = Array ($output,$cmd); 02377 02378 $ret = exec($cmd); 02379 t3lib_div::fixPermissions($this->wrapFileName($output)); // Change the permissions of the file 02380 02381 return $ret; 02382 } 02383 } 02384 02395 function combineExec($input,$overlay,$mask,$output) { 02396 if (!$this->NO_IMAGE_MAGICK) { 02397 $cmd = t3lib_div::imageMagickCommand('combine', '-compose over '.$this->wrapFileName($input).' '.$this->wrapFileName($overlay).' '.$this->wrapFileName($mask).' '.$this->wrapFileName($output)); 02398 $this->IM_commands[] = Array ($output,$cmd); 02399 02400 $ret = exec($cmd); 02401 t3lib_div::fixPermissions($this->wrapFileName($output)); // Change the permissions of the file 02402 02403 return $ret; 02404 } 02405 } 02406 02414 function wrapFileName($inputName) { 02415 if (strstr($inputName,' ')) { 02416 $inputName='"'.$inputName.'"'; 02417 } 02418 return $inputName; 02419 } 02420 02421 02422 02423 02424 02425 02426 02427 02428 02429 02430 02431 02432 02433 02434 02435 02436 02437 02438 02439 02440 02441 02442 02443 /*********************************** 02444 * 02445 * Various IO functions 02446 * 02447 ***********************************/ 02448 02455 function checkFile($file) { 02456 if (@is_file($file)) { 02457 return $file; 02458 } else { 02459 return ''; 02460 } 02461 } 02462 02469 function createTempSubDir($dirName) { 02470 02471 // Checking if the this->tempPath is already prefixed with PATH_site and if not, prefix it with that constant. 02472 if (t3lib_div::isFirstPartOfStr($this->tempPath,PATH_site)) { 02473 $tmpPath = $this->tempPath; 02474 } else { 02475 $tmpPath = PATH_site.$this->tempPath; 02476 } 02477 02478 // Making the temporary filename: 02479 if (!@is_dir($tmpPath.$dirName)) { 02480 return t3lib_div::mkdir($tmpPath.$dirName); 02481 } 02482 } 02483 02491 function applyImageMagickToPHPGif(&$im, $command) { 02492 $tmpStr = $this->randomName(); 02493 $theFile = $tmpStr.'.'.$this->gifExtension; 02494 $this->ImageGif($im, $theFile); 02495 $this->imageMagickExec($theFile,$theFile,$command); 02496 $tmpImg = $this->imageCreateFromFile($theFile); 02497 if ($tmpImg) { 02498 ImageDestroy($im); 02499 $im = $tmpImg; 02500 $this->w = imagesx($im); 02501 $this->h = imagesy($im); 02502 } 02503 if (!$this->dontUnlinkTempFiles) { 02504 unlink($theFile); 02505 } 02506 } 02507 02517 function gif_or_jpg($type,$w,$h) { 02518 if ($type=='ai' || $w*$h < $this->pixelLimitGif) { 02519 return $this->gifExtension; 02520 } else { 02521 return 'jpg'; 02522 } 02523 } 02524 02534 function output($file) { 02535 if ($file) { 02536 ereg('([^\.]*)$',$file,$reg); 02537 $ext=strtolower($reg[0]); 02538 switch($ext) { 02539 case $this->gifExtension: 02540 if ($this->ImageGif($this->im, $file)) { 02541 // ImageMagick operations 02542 if($this->setup['reduceColors']) { 02543 $this->imageMagickExec($file,$file,' -colors '.t3lib_div::intInRange($this->setup['reduceColors'],2,255)); 02544 t3lib_div::gif_compress($file,''); // Compress with IM (lzw) or GD (rle) (Workaround for the absence of lzw-compression in GD) 02545 } else { 02546 t3lib_div::gif_compress($file, 'IM'); // Compress with IM! (adds extra compression, LZW from ImageMagick) (Workaround for the absence of lzw-compression in GD) 02547 } 02548 } 02549 break; 02550 case 'jpg': 02551 case 'jpeg': 02552 $tmpStr = $this->randomName(); 02553 $theFile = $tmpStr.'.'.$this->gifExtension; 02554 if ($this->ImageGif($this->im, $theFile)) { 02555 // ImageMagick operations 02556 $operations=''; 02557 if($this->setup['quality']) { 02558 $operations.=' -quality '.t3lib_div::intInRange($this->setup['quality'],10,100); 02559 } 02560 $this->imageMagickExec($theFile,$file,$operations); 02561 if (!$this->dontUnlinkTempFiles) { 02562 unlink($theFile); 02563 } 02564 } 02565 break; 02566 } 02567 $GLOBALS['TEMP_IMAGES_ON_PAGE'][]=$file; 02568 } 02569 return $file; 02570 } 02571 02578 function destroy() { 02579 ImageDestroy($this->im); 02580 } 02581 02588 function imgTag ($imgInfo) { 02589 return '<img src="'.$imgInfo[3].'" width="'.$imgInfo[0].'" height="'.$imgInfo[1].'" border="0" alt="" />'; 02590 } 02591 02600 function ImageGif($destImg, $theImage) { 02601 imageinterlace ($destImg,0); 02602 if ($this->gifExtension=='gif') { 02603 return ImageGif($destImg, $theImage); 02604 } 02605 if ($this->gifExtension=='png') { 02606 return ImagePng($destImg, $theImage); 02607 } 02608 } 02609 02618 function imageCreateFromGif($sourceImg) { 02619 return $this->imageCreateFromFile($sourceImg); 02620 } 02621 02629 function imageCreateFromFile($sourceImg) { 02630 $imgInf = pathinfo($sourceImg); 02631 $ext = strtolower($imgInf['extension']); 02632 02633 if ($ext=='gif' && function_exists('imagecreatefromgif')) { 02634 return imageCreateFromGif($sourceImg); 02635 } elseif ($ext=='png' && function_exists('imagecreatefrompng')) { 02636 return imageCreateFromPng($sourceImg); 02637 } elseif (($ext=='jpg' || $ext=='jpeg') && function_exists('imagecreatefromjpeg')) { 02638 return imageCreateFromJpeg($sourceImg); 02639 } 02640 02641 // If non of the above: 02642 $i = @getimagesize($sourceImg); 02643 $im = imagecreate($i[0],$i[1]); 02644 ImageColorAllocate($im, 128,128,128); 02645 return $im; 02646 } 02647 } 02648 02649 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']) { 02650 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']); 02651 } 02652 ?>