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