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