/***************************************************************
* Copyright notice
*
-* (c) 1999-2004 Kasper Skaarhoj (kasper@typo3.com)
+* (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* $Id$
* Revised for TYPO3 3.6 July/2003 by Kasper Skaarhoj
*
- * @author Kasper Skaarhoj <kasper@typo3.com>
+ * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
*/
/**
* [CLASS/FUNCTION INDEX of SCRIPT]
*
*
*
- * 147: class t3lib_stdGraphic
- * 224: function init()
+ * 155: class t3lib_stdGraphic
+ * 236: function init()
*
* SECTION: Layering images / "IMAGE" GIFBUILDER object
- * 324: function maskImageOntoImage(&$im,$conf,$workArea)
- * 384: function copyImageOntoImage(&$im,$conf,$workArea)
- * 406: function copyGifOntoGif(&$im,$cpImg,$conf,$workArea)
- * 485: function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)
+ * 366: function maskImageOntoImage(&$im,$conf,$workArea)
+ * 436: function copyImageOntoImage(&$im,$conf,$workArea)
+ * 458: function copyGifOntoGif(&$im,$cpImg,$conf,$workArea)
+ * 537: function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)
*
* SECTION: Text / "TEXT" GIFBUILDER object
- * 534: function makeText(&$im,$conf,$workArea)
- * 650: function txtPosition($conf,$workArea,$BB)
- * 704: function calcBBox($conf)
- * 773: function addToMap($cords,$conf)
- * 796: function calcTextCordsForMap($cords,$offset, $conf)
- * 831: function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1)
- * 868: function fontResize($conf)
- * 910: function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1)
- * 951: function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1)
- * 980: function splitString($string,$splitRendering,$fontSize,$fontFile)
+ * 587: function makeText(&$im,$conf,$workArea)
+ * 707: function txtPosition($conf,$workArea,$BB)
+ * 761: function calcBBox($conf)
+ * 820: function addToMap($cords,$conf)
+ * 843: function calcTextCordsForMap($cords,$offset, $conf)
+ * 878: function SpacedImageTTFText(&$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF=1)
+ * 915: function fontResize($conf)
+ * 958: function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF=1)
+ * 1005: function ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering,$sF=1)
+ * 1058: function splitString($string,$splitRendering,$fontSize,$fontFile)
+ * 1208: function calcWordSpacing($conf, $scaleFactor=1)
+ * 1227: function getTextScalFactor($conf)
*
* SECTION: Other GIFBUILDER objects related to TEXT
- * 1136: function makeOutline(&$im,$conf,$workArea,$txtConf)
- * 1165: function circleOffset($distance, $iterations)
- * 1189: function makeEmboss(&$im,$conf,$workArea,$txtConf)
- * 1211: function makeShadow(&$im,$conf,$workArea,$txtConf)
+ * 1262: function makeOutline(&$im,$conf,$workArea,$txtConf)
+ * 1291: function circleOffset($distance, $iterations)
+ * 1315: function makeEmboss(&$im,$conf,$workArea,$txtConf)
+ * 1337: function makeShadow(&$im,$conf,$workArea,$txtConf)
*
* SECTION: Other GIFBUILDER objects
- * 1341: function makeBox(&$im,$conf,$workArea)
- * 1360: function makeEffect(&$im, $conf)
- * 1375: function IMparams($setup)
- * 1458: function adjust(&$im, $conf)
- * 1490: function crop(&$im,$conf)
- * 1520: function scale(&$im,$conf)
- * 1552: function setWorkArea($workArea)
+ * 1469: function makeBox(&$im,$conf,$workArea)
+ * 1491: function makeEffect(&$im, $conf)
+ * 1506: function IMparams($setup)
+ * 1589: function adjust(&$im, $conf)
+ * 1621: function crop(&$im,$conf)
+ * 1652: function scale(&$im,$conf)
+ * 1684: function setWorkArea($workArea)
*
* SECTION: Adjustment functions
- * 1593: function autolevels(&$im)
- * 1624: function outputLevels(&$im,$low,$high,$swap='')
- * 1656: function inputLevels(&$im,$low,$high,$swap='')
- * 1687: function reduceColors(&$im,$limit, $cols)
+ * 1725: function autolevels(&$im)
+ * 1756: function outputLevels(&$im,$low,$high,$swap='')
+ * 1788: function inputLevels(&$im,$low,$high,$swap='')
+ * 1819: function reduceColors(&$im,$limit, $cols)
+ * 1832: function IMreduceColors($file, $cols)
*
* SECTION: GIFBUILDER Helper functions
- * 1725: function prependAbsolutePath($fontFile)
- * 1739: function v5_sharpen($factor)
- * 1758: function v5_blur($factor)
- * 1775: function randomName()
- * 1788: function applyOffset($cords,$OFFSET)
- * 1801: function convertColor($string)
- * 1851: function recodeString($string)
- * 1873: function singleChars($theText,$returnUnicodeNumber=FALSE)
- * 1896: function objPosition($conf,$workArea,$BB)
+ * 1875: function prependAbsolutePath($fontFile)
+ * 1889: function v5_sharpen($factor)
+ * 1908: function v5_blur($factor)
+ * 1925: function randomName()
+ * 1938: function applyOffset($cords,$OFFSET)
+ * 1951: function convertColor($string)
+ * 2001: function recodeString($string)
+ * 2023: function singleChars($theText,$returnUnicodeNumber=FALSE)
+ * 2046: function objPosition($conf,$workArea,$BB)
*
* SECTION: Scaling, Dimensions of images
- * 1975: function imageMagickConvert($imagefile,$newExt='',$w='',$h='',$params='',$frame='',$options='',$mustCreate=0)
- * 2063: function getImageDimensions($imageFile)
- * 2091: function cacheImageDimensions($identifyResult)
- * 2123: function getCachedImageDimensions($imageFile)
- * 2157: function getImageScale($info,$w,$h,$options)
- * 2245: function file_exists_typo3temp_file($output,$orig='')
+ * 2125: function imageMagickConvert($imagefile,$newExt='',$w='',$h='',$params='',$frame='',$options='',$mustCreate=0)
+ * 2238: function getImageDimensions($imageFile)
+ * 2266: function cacheImageDimensions($identifyResult)
+ * 2298: function getCachedImageDimensions($imageFile)
+ * 2332: function getImageScale($info,$w,$h,$options)
+ * 2438: function file_exists_typo3temp_file($output,$orig='')
*
* SECTION: ImageMagick API functions
- * 2306: function imageMagickIdentify($imagefile)
- * 2340: function imageMagickExec($input,$output,$params)
- * 2358: function combineExec($input,$overlay,$mask,$output)
- * 2373: function wrapFileName($inputName)
+ * 2499: function imageMagickIdentify($imagefile)
+ * 2534: function imageMagickExec($input,$output,$params)
+ * 2557: function combineExec($input,$overlay,$mask,$output, $handleNegation = false)
+ * 2588: function wrapFileName($inputName)
*
* SECTION: Various IO functions
- * 2414: function checkFile($file)
- * 2428: function createTempSubDir($dirName)
- * 2450: function applyImageMagickToPHPGif(&$im, $command)
- * 2476: function gif_or_jpg($type,$w,$h)
- * 2493: function output($file)
- * 2537: function destroy()
- * 2547: function imgTag ($imgInfo)
- * 2559: function ImageGif($destImg, $theImage)
- * 2576: function imageCreateFromGif($sourceImg)
+ * 2629: function checkFile($file)
+ * 2643: function createTempSubDir($dirName)
+ * 2665: function applyImageMagickToPHPGif(&$im, $command)
+ * 2691: function gif_or_jpg($type,$w,$h)
+ * 2708: function output($file)
+ * 2748: function destroy()
+ * 2758: function imgTag ($imgInfo)
+ * 2770: function ImageWrite($destImg, $theImage)
+ * 2808: function imageGif($destImg, $theImage)
+ * 2820: function imageCreateFromGif($sourceImg)
+ * 2831: function imageCreateFromFile($sourceImg)
+ * 2870: function imagecreate($w, $h)
+ * 2885: function hexColor($col)
+ * 2903: function unifyColors(&$img, $colArr, $closest = false)
*
- * TOTAL FUNCTIONS: 58
+ * TOTAL FUNCTIONS: 66
* (This index is automatically created/updated by the extension "extdeveval")
*
*/
* Class contains a bunch of cool functions for manipulating graphics with GDlib/Freetype and ImageMagick
* VERY OFTEN used with gifbuilder that extends this class and provides a TypoScript API to using these functions
*
- * @author Kasper Skaarhoj <kasper@typo3.com>
+ * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
* @package TYPO3
* @subpackage t3lib
* @see tslib_gifBuilder
var $GD2=0; // Set, if the GDlib used is version 2.
var $imagecopyresized_fix=0; // If set, imagecopyresized will not be called directly. For GD2 (some PHP installs?)
var $gifExtension = 'gif'; // This should be changed to 'png' if you want this class to read/make PNG-files instead!
+ var $gdlibExtensions = ''; // File formats supported by gdlib. This variable get's filled in "init" method
+ var $truecolor = true; // Internal variable which get's used to determine wheter GDlib should use function truecolor pendants
+ var $png_truecolor = false; // Set to true if generated png's should be truecolor by default
+ var $truecolorColors = 0xffffff; // 16777216 Colors is the maximum value for PNG, JPEG truecolor images (24-bit, 8-bit / Channel)
var $TTFLocaleConv = ''; // Used to recode input to TTF-functions for other charsets.
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.
- var $imageMagickPath = ''; // path to imageMagick, eg: /usr/lib/
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!
var $webImageExt = 'gif,jpg,jpeg,png'; // Commalist of web image extensions (can be shown by a webbrowser)
var $maskNegate = ''; // Will be ' -negate' if ImageMagick ver 5.2+. See init();
);
var $NO_IMAGE_MAGICK = '';
var $V5_EFFECTS = 0;
+ var $im_version_4 = 0;
var $mayScaleUp = 1;
// Variables for testing, alternative usage etc.
'white' => Array(255,255,255)
);
- // Charset conversion object:
+ /**
+ * Charset conversion object:
+ *
+ * @var t3lib_cs
+ */
var $csConvObj;
var $nativeCharset=''; // Is set to the native character set of the input strings.
function init() {
$gfxConf = $GLOBALS['TYPO3_CONF_VARS']['GFX'];
+ if (function_exists('imagecreatefromjpeg')&&function_exists('imagejpeg')) {
+ $this->gdlibExtensions .= ',jpg,jpeg';
+ }
+ if (function_exists('imagecreatefrompng')&&function_exists('imagepng')) {
+ $this->gdlibExtensions .= ',png';
+ }
+ if (function_exists('imagecreatefromgif')&&function_exists('imagegif')) {
+ $this->gdlibExtensions .= ',gif';
+ }
+ if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['png_truecolor']) {
+ $this->png_truecolor = true;
+ }
+ if (!$gfxConf['gdlib_2'] || !function_exists('imagecreatetruecolor')) {
+ $this->truecolor = false;
+ }
+ if (!$gfxConf['im_version_5']) {
+ $this->im_version_4 = true;
+ }
+
+ // When GIFBUILDER gets used in truecolor mode (GD2 required)
+ if ($this->truecolor) {
+ if ($this->png_truecolor) {
+ $this->cmds['png'] = ''; // No colors parameter if we generate truecolor images.
+ }
+ $this->cmds['gif'] = ''; // No colors parameter if we generate truecolor images.
+ }
+
// Setting default JPG parameters:
- $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.intval($gfxConf['im_jpg_quality']);
+ $this->jpegQuality = t3lib_div::intInRange($gfxConf['jpg_quality'], 10, 100, 75);
+ $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -sharpen 50 -quality '.$this->jpegQuality;
if ($gfxConf['im_combine_filename']) $this->combineScript=$gfxConf['im_combine_filename'];
if ($gfxConf['im_noFramePrepended']) $this->noFramePrepended=1;
$this->enable_typo3temp_db_tracking = $gfxConf['enable_typo3temp_db_tracking'];
}
- $this->imageMagickPath = $gfxConf['im_path'];
$this->imageFileExt = $gfxConf['imagefile_ext'];
// This should be set if ImageMagick ver. 5+ is used.
// - therefore must be disabled in order not to perform sharpen, blurring and such.
$this->NO_IM_EFFECTS = 1;
- $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['im_jpg_quality']);
+ $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.$this->jpegQuality;
}
- // ... but if 'im_v5effects' is set, dont care about 'im_no_effects'
+ // ... but if 'im_v5effects' is set, don't care about 'im_no_effects'
if ($gfxConf['im_v5effects']) {
$this->NO_IM_EFFECTS = 0;
$this->V5_EFFECTS = 1;
if ($gfxConf['im_v5effects']>0) {
- $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['im_jpg_quality']).$this->v5_sharpen(10);
+ $this->cmds['jpg'] = $this->cmds['jpeg'] = '-colorspace RGB -quality '.intval($gfxConf['jpg_quality']).$this->v5_sharpen(10);
}
}
}
if (TYPO3_MODE=='FE') {
- $this->csConvObj = &$GLOBALS['TSFE']->csConvObj;
- } else { // BE assumed:
- $this->csConvObj = &$GLOBALS['LANG']->csConvObj;
+ $this->csConvObj = $GLOBALS['TSFE']->csConvObj;
+ } elseif(is_object($GLOBALS['LANG'])) { // BE assumed:
+ $this->csConvObj = $GLOBALS['LANG']->csConvObj;
+ } else { // The object may not exist yet, so we need to create it now. Happens in the Install Tool for example.
+ $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
}
$this->nativeCharset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'];
}
*/
function maskImageOntoImage(&$im,$conf,$workArea) {
if ($conf['file'] && $conf['mask']) {
- $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','','');
- $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','','');
+ $imgInf = pathinfo($conf['file']);
+ $imgExt = strtolower($imgInf['extension']);
+ if (!t3lib_div::inList($this->gdlibExtensions, $imgExt)) {
+ $BBimage = $this->imageMagickConvert($conf['file'],$this->gifExtension,'','','','','');
+ } else {
+ $BBimage = $this->getImageDimensions($conf['file']);
+ }
+ $maskInf = pathinfo($conf['mask']);
+ $maskExt = strtolower($maskInf['extension']);
+ if (!t3lib_div::inList($this->gdlibExtensions, $maskExt)) {
+ $BBmask = $this->imageMagickConvert($conf['mask'],$this->gifExtension,'','','','','');
+ } else {
+ $BBmask = $this->getImageDimensions($conf['mask']);
+ }
if ($BBimage && $BBmask) {
$w = imagesx($im);
$h = imagesy($im);
$theImage = $tmpStr.'_img.'.$this->gifExtension;
$theDest = $tmpStr.'_dest.'.$this->gifExtension;
$theMask = $tmpStr.'_mask.'.$this->gifExtension;
- $theMask2 = $tmpStr.'_mask2.'.trim($GLOBALS['TYPO3_CONF_VARS']['GFX']['im_mask_temp_ext_noloss']);
// prepare overlay image
- $cpImg = $this->imageCreateFromGif($BBimage[3]);
- $destImg = imagecreate($w,$h);
- ImageColorAllocate($destImg, 0,0,0);
+ $cpImg = $this->imageCreateFromFile($BBimage[3]);
+ $destImg = $this->imagecreate($w,$h);
+ $Bcolor = ImageColorAllocate($destImg, 0,0,0);
+ ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
$this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
- $this->ImageGif($destImg, $theImage);
+ $this->ImageWrite($destImg, $theImage);
imageDestroy($cpImg);
imageDestroy($destImg);
// prepare mask image
- $cpImg = $this->imageCreateFromGif($BBmask[3]);
- $destImg = imagecreate($w,$h);
- ImageColorAllocate($destImg, 0,0,0);
+ $cpImg = $this->imageCreateFromFile($BBmask[3]);
+ $destImg = $this->imagecreate($w,$h);
+ $Bcolor = ImageColorAllocate($destImg, 0, 0, 0);
+ ImageFilledRectangle($destImg, 0, 0, $w, $h, $Bcolor);
$this->copyGifOntoGif($destImg,$cpImg,$conf,$workArea);
- $this->ImageGif($destImg, $theMask);
+ $this->ImageWrite($destImg, $theMask);
imageDestroy($cpImg);
imageDestroy($destImg);
- // treat the mask
- $this->imageMagickExec($theMask,$theMask2,'-colorspace GRAY'.$this->maskNegate);
// mask the images
- $this->ImageGif($im, $theDest);
+ $this->ImageWrite($im, $theDest);
- $this->combineExec($theDest,$theImage,$theMask2,$theDest);
+ $this->combineExec($theDest,$theImage,$theMask,$theDest, true); // Let combineExec handle maskNegation
- $backIm = $this->imageCreateFromGif($theDest); // The main image is loaded again...
+ $backIm = $this->imageCreateFromFile($theDest); // The main image is loaded again...
if ($backIm) { // ... and if nothing went wrong we load it onto the old one.
ImageColorTransparent($backIm,-1);
$im = $backIm;
unlink($theDest);
unlink($theImage);
unlink($theMask);
- unlink($theMask2);
}
}
}
*/
function copyImageOntoImage(&$im,$conf,$workArea) {
if ($conf['file']) {
- if ($conf['BBOX'][2]!=$this->gifExtension) {
+ if (!t3lib_div::inList($this->gdlibExtensions, $conf['BBOX'][2])) {
$conf['BBOX']=$this->imageMagickConvert($conf['BBOX'][3],$this->gifExtension,'','','','','');
$conf['file']=$conf['BBOX'][3];
}
- $cpImg = $this->imageCreateFromGif($conf['file']);
+ $cpImg = $this->imageCreateFromFile($conf['file']);
$this->copyGifOntoGif($im,$cpImg,$conf,$workArea);
imageDestroy($cpImg);
}
*/
function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) {
if ($this->imagecopyresized_fix) {
- $im_base = imagecreatetruecolor(imagesx($im), imagesy($im)); // Make true color image
+ $im_base = $this->imagecreate(imagesx($im), imagesy($im)); // Make true color image
imagecopyresized($im_base, $im, 0,0,0,0, imagesx($im),imagesy($im),imagesx($im),imagesy($im)); // Copy the source image onto that
imagecopyresized($im_base, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h); // Then copy the $cpImg onto that (the actual operation!)
$im = $im_base; // Set pointer
- $this->makeEffect($im, Array('value'=>'colors=256')); // Reduce colors to 256 - make SURE that IM is working then!
+ if (!$this->truecolor) {
+ $this->makeEffect($im, Array('value'=>'colors='.t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256))); // Reduce to "reduceColors" colors - make SURE that IM is working then!
+ }
} else {
imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
}
-
/********************************
*
* Text / "TEXT" GIFBUILDER object
*/
function makeText(&$im,$conf,$workArea) {
// Spacing
- $spacing = intval($conf['spacing']);
- $wordSpacing = intval($conf['wordSpacing']);
- $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
+ list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
// Position
$txtPos = $this->txtPosition($conf,$workArea,$conf['BBOX']);
$theText = $this->recodeString($conf['text']);
// NiceText is calculated
if (!$conf['niceText']) {
// Font Color is reserved:
- $this->reduceColors($im,256, 200);
+ if (!$this->truecolor) {
+ $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
+ $this->reduceColors($im, $reduce-49, $reduce-50); // If "reduce-49" colors (or more) are used reduce them to "reduce-50"
+ }
$Fcolor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
// antiAliasing is setup:
$Fcolor = ($conf['antiAlias']) ? $Fcolor : -$Fcolor;
if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function:
$this->SpacedImageTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.']);
} else {
- $this->ImageTTFTextWrapper($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.']);
+ $this->renderTTFText($im, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'], $conf);
}
}
} else { // NICETEXT::
$newH = ceil($sF*imagesy($im));
// Make mask
- $maskImg = imagecreate($newW, $newH);
- ImageColorAllocate($maskImg, 255,255,255);
+ $maskImg = $this->imagecreate($newW, $newH);
+ $Bcolor = ImageColorAllocate($maskImg, 255,255,255);
+ ImageFilledRectangle($maskImg, 0, 0, $newW, $newH, $Bcolor);
$Fcolor = ImageColorAllocate($maskImg, 0,0,0);
if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function:
$this->SpacedImageTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, t3lib_stdGraphic::prependAbsolutePath($conf['fontFile']), $theText, $spacing, $wordSpacing, $conf['splitRendering.'],$sF);
} else {
- $this->ImageTTFTextWrapper($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
+ $this->renderTTFText($maskImg, $conf['fontSize'], $conf['angle'], $txtPos[0], $txtPos[1], $Fcolor, $conf['fontFile'], $theText, $conf['splitRendering.'], $conf, $sF);
}
- $this->ImageGif($maskImg, $fileMask);
+ $this->ImageWrite($maskImg, $fileMask);
ImageDestroy($maskImg);
// Downscales the mask
}
}
}
+
$this->imageMagickExec($fileMask,$fileMask,$command);
// Make the color-file
- $colorImg = imagecreate($w,$h);
- ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]);
- $this->ImageGif($colorImg, $fileColor);
+ $colorImg = $this->imagecreate($w,$h);
+ $Ccolor = ImageColorAllocate($colorImg, $cols[0],$cols[1],$cols[2]);
+ ImageFilledRectangle($colorImg, 0, 0, $w, $h, $Ccolor);
+ $this->ImageWrite($colorImg, $fileColor);
ImageDestroy($colorImg);
// The mask is applied
- $this->ImageGif($im, $fileMenu); // The main pictures is saved temporarily
+ $this->ImageWrite($im, $fileMenu); // The main pictures is saved temporarily
- $this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu);
+ $this->combineExec($fileMenu,$fileColor,$fileMask, $fileMenu);
- $backIm = $this->imageCreateFromGif($fileMenu); // The main image is loaded again...
+ $backIm = $this->imageCreateFromFile($fileMenu); // The main image is loaded again...
if ($backIm) { // ... and if nothing went wrong we load it onto the old one.
ImageColorTransparent($backIm,-1);
$im = $backIm;
* @see txtPosition(), tslib_gifBuilder::start()
*/
function calcBBox($conf) {
- if (!$conf['niceText']) {
- $sF = 1;
- } else { // NICETEXT::
- $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
- }
-
- $spacing = intval($conf['spacing']);
- $wordSpacing = intval($conf['wordSpacing']);
- $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
-
- $spacing*=$sF;
- $wordSpacing*=$sF;
+ $sF = $this->getTextScalFactor($conf);
+ list($spacing,$wordSpacing) = $this->calcWordSpacing($conf, $sF);
$theText = $this->recodeString($conf['text']);
$charInf = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $theText, $conf['splitRendering.'],$sF);
$x = ($charInf[2]-$charInf[0]);
$y = ($charInf[1]-$charInf[7]);
}
+ // Set original lineHeight (used by line breaks):
+ $theBBoxInfo['lineHeight'] = $y;
+
if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function:
$x=0;
if (!$spacing && $wordSpacing) {
$x+=$charW+(($char==' ')?$wordSpacing:$spacing);
}
}
+ } elseif (isset($conf['breakWidth']) && $conf['breakWidth'] && $this->getRenderedTextWidth($conf['text'], $conf) > $conf['breakWidth']) {
+ $maxWidth = 0;
+ $currentWidth = 0;
+ $breakWidth = $conf['breakWidth'];
+ $breakSpace = $this->getBreakSpace($conf, $theBBoxInfo);
+
+ $wordPairs = $this->getWordPairsForLineBreak($conf['text']);
+ // Iterate through all word pairs:
+ foreach ($wordPairs as $index => $wordPair) {
+ $wordWidth = $this->getRenderedTextWidth($wordPair, $conf);
+ if ($index == 0 || $currentWidth + $wordWidth <= $breakWidth) {
+ $currentWidth+= $wordWidth;
+ } else {
+ $maxWidth = max($maxWidth, $currentWidth);
+ $y+= $breakSpace;
+ // Restart:
+ $currentWidth = $wordWidth;
+ }
+ }
+ $x = max($maxWidth, $currentWidth) * $sF;
}
- if ($sF>1) {
- $x = ceil($x/$sF);
- $y = ceil($y/$sF);
+ if ($sF > 1) {
+ $x = ceil($x / $sF);
+ $y = ceil($y / $sF);
if (is_array($theBBoxInfo)) {
- reset($theBBoxInfo);
- while(list($key,$val)=each($theBBoxInfo)) {
- $theBBoxInfo[$key]=ceil($theBBoxInfo[$key]/$sF);
+ foreach ($theBBoxInfo as &$value) {
+ $value = ceil($value / $sF);
}
}
}
- return Array($x,$y,$theBBoxInfo);
+ return array($x, $y, $theBBoxInfo);
}
/**
* @param array The TypoScript properties of the TEXT GIFBUILDER object
* @return integer The new fontSize
* @access private
- * @author Rene Fritz <r.fritz@colorcube.de>
+ * @author Rene Fritz <r.fritz@colorcube.de>
* @see tslib_gifBuilder::start()
*/
function fontResize($conf) {
// 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!!!!
$maxWidth = intval($conf['maxWidth']);
+ list($spacing,$wordSpacing) = $this->calcWordSpacing($conf);
if ($maxWidth) {
if ($spacing || $wordSpacing) { // If any kind of spacing applys, we use this function:
return $conf['fontSize'];
// Traverse string parts:
foreach($stringParts as $strCfg) {
+ $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
+ if (is_readable($fontFile)) {
+
+ // Calculate Bounding Box for part:
+ $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $fontFile, $strCfg['str']);
- // Calculate Bounding Box for part:
- $calc = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
+ // Calculate offsets:
+ if (!count($offsetInfo)) {
+ $offsetInfo = $calc; // First run, just copy over.
+ } else {
+ $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
+ $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
+ $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
+ $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
+ }
- // Calculate offsets:
- if (!count($offsetInfo)) {
- $offsetInfo = $calc; // First run, just copy over.
} else {
- $offsetInfo[2]+=$calc[2]-$calc[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
- $offsetInfo[3]+=$calc[3]-$calc[1]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
- $offsetInfo[4]+=$calc[4]-$calc[6]+intval($splitRendering['compX'])+intval($strCfg['xSpaceBefore'])+intval($strCfg['xSpaceAfter']);
- $offsetInfo[5]+=$calc[5]-$calc[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceBefore'])-intval($strCfg['ySpaceAfter']);
+ debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFBBoxWrapper()');
}
}
$y-= intval($strCfg['ySpaceBefore']);
}
- // Render part:
- ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
+ $fontFile = t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']);
+ if (is_readable($fontFile)) {
+
+ // Render part:
+ ImageTTFText($im, t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, $x, $y, $colorIndex, $fontFile, $strCfg['str']);
+
+ // Calculate offset to apply:
+ $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
+ $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']);
+ $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']);
+
+ } else {
+ debug('cannot read file: '.$fontFile, 't3lib_stdGraphic::ImageTTFTextWrapper()');
+ }
- // Calculate offset to apply:
- $wordInf = ImageTTFBBox(t3lib_div::freetypeDpiComp($sF*$strCfg['fontSize']), $angle, t3lib_stdGraphic::prependAbsolutePath($strCfg['fontFile']), $strCfg['str']);
- $x+= $wordInf[2]-$wordInf[0]+intval($splitRendering['compX'])+intval($strCfg['xSpaceAfter']);
- $y+= $wordInf[5]-$wordInf[7]-intval($splitRendering['compY'])-intval($strCfg['ySpaceAfter']);
}
}
/**
* Splitting a string for ImageTTFBBox up into an array where each part has its own configuration options.
*
- * @param [type] $string: ...
- * @param [type] $splitRendering: ...
- * @param [type] $fontSize: ...
- * @param [type] $fontFile: ...
- * @return [type] ...
+ * @param string UTF-8 string
+ * @param array Split-rendering configuration from GIFBUILDER TEXT object.
+ * @param integer Current fontsize
+ * @param string Current font file
+ * @return array Array with input string splitted according to configuration
*/
function splitString($string,$splitRendering,$fontSize,$fontFile) {
return $result;
}
+ /**
+ * Calculates the spacing and wordSpacing values
+ *
+ * @param array TypoScript array for the TEXT GIFBUILDER object
+ * @param integer TypoScript value from eg $conf['niceText.']['scaleFactor']
+ * @return array Array with two keys [0]/[1] being array($spacing,$wordSpacing)
+ * @access private
+ * @see calcBBox()
+ */
+ function calcWordSpacing($conf, $scaleFactor=1) {
+
+ $spacing = intval($conf['spacing']);
+ $wordSpacing = intval($conf['wordSpacing']);
+ $wordSpacing = $wordSpacing?$wordSpacing:$spacing*2;
+
+ $spacing*=$scaleFactor;
+ $wordSpacing*=$scaleFactor;
+
+ return array($spacing,$wordSpacing);
+ }
+
+ /**
+ * Calculates and returns the niceText.scaleFactor
+ *
+ * @param array TypoScript array for the TEXT GIFBUILDER object
+ * @return integer TypoScript value from eg $conf['niceText.']['scaleFactor']
+ * @access private
+ */
+ function getTextScalFactor($conf) {
+ if (!$conf['niceText']) {
+ $sF = 1;
+ } else { // NICETEXT::
+ $sF = t3lib_div::intInRange($conf['niceText.']['scaleFactor'],2,5);
+ }
+ return $sF;
+ }
+
+ /**
+ * Renders a regular text and takes care of a possible line break automatically.
+ *
+ * @param pointer (See argument for PHP function imageTTFtext())
+ * @param integer (See argument for PHP function imageTTFtext())
+ * @param integer (See argument for PHP function imageTTFtext())
+ * @param integer (See argument for PHP function imageTTFtext())
+ * @param integer (See argument for PHP function imageTTFtext())
+ * @param integer (See argument for PHP function imageTTFtext())
+ * @param string (See argument for PHP function imageTTFtext())
+ * @param string (See argument for PHP function imageTTFtext()). UTF-8 string, possibly with entities in.
+ * @param array Split-rendering configuration
+ * @param integer Scale factor
+ * @param array $conf: The configuration
+ * @return void
+ */
+ protected function renderTTFText(&$im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering, $conf, $sF = 1) {
+ if (isset($conf['breakWidth']) && $conf['breakWidth'] && $this->getRenderedTextWidth($string, $conf) > $conf['breakWidth']) {
+ $phrase = '';
+ $currentWidth = 0;
+
+ $breakWidth = $conf['breakWidth'];
+ $breakSpace = $this->getBreakSpace($conf);
+
+ $wordPairs = $this->getWordPairsForLineBreak($string);
+ // Iterate through all word pairs:
+ foreach ($wordPairs as $index => $wordPair) {
+ $wordWidth = $this->getRenderedTextWidth($wordPair, $conf);
+ if ($index == 0 || $currentWidth + $wordWidth <= $breakWidth) {
+ $currentWidth+= $wordWidth;
+ $phrase.= $wordPair;
+ } else {
+ // Render the current phrase that is below breakWidth:
+ $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $phrase, $splitRendering, $sF);
+ // Calculate the news height offset:
+ $y+= $breakSpace;
+ // Restart the phrase:
+ $currentWidth = $wordWidth;
+ $phrase = $wordPair;
+ }
+ }
+ // Render the remaining phrase:
+ if ($currentWidth) {
+ $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $phrase, $splitRendering, $sF);
+ }
+ } else {
+ $this->ImageTTFTextWrapper($im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering, $sF);
+ }
+ }
+
+ /**
+ * Gets the word pairs used for automatic line breaks.
+ *
+ * @param string $string
+ * @return array
+ */
+ protected function getWordPairsForLineBreak($string) {
+ $wordPairs = array();
+
+ $wordsArray = preg_split('#([ -.,!:]+)#', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $wordsCount = count($wordsArray);
+ for ($index=0; $index < $wordsCount; $index+= 2) {
+ $wordPairs[] = $wordsArray[$index] . $wordsArray[$index + 1];
+ }
+
+ return $wordPairs;
+ }
+
+ /**
+ * Gets the rendered text width.
+ *
+ * @param string $text
+ * @param array $conf
+ * @param integer
+ */
+ protected function getRenderedTextWidth($text, $conf) {
+ $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $this->recodeString($text), $conf['splitRendering.']);
+ if ($conf['angle']< 0) {
+ $pixelWidth = abs($bounds[4]-$bounds[0]);
+ } elseif ($conf['angle'] > 0) {
+ $pixelWidth = abs($bounds[2]-$bounds[6]);
+ } else {
+ $pixelWidth = abs($bounds[4]-$bounds[6]);
+ }
+ return $pixelWidth;
+ }
+ /**
+ * Gets the break space for each new line.
+ *
+ * @param array $conf: TypoScript configuration for the currently rendered object
+ * @param array $boundingBox: The bounding box the the currently rendered object
+ * @return integer The break space
+ */
+ protected function getBreakSpace($conf, array $boundingBox = NULL) {
+ if (!isset($boundingBox)) {
+ $boundingBox = $this->calcBBox($conf);
+ $boundingBox = $boundingBox[2];
+ }
+ if (isset($conf['breakSpace']) && $conf['breakSpace']) {
+ $breakSpace = $boundingBox['lineHeight'] * $conf['breakSpace'];
+ } else {
+ $breakSpace = $boundingBox['lineHeight'];
+ }
+ return $breakSpace;
+ }
$fileMask = $tmpStr.'_mask.'.$this->gifExtension;
// BlurColor Image laves
- $blurColImg = imagecreate($w,$h);
+ $blurColImg = $this->imagecreate($w,$h);
$bcols=$this->convertColor($conf['color']);
- ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]);
- $this->ImageGif($blurColImg, $fileColor);
+ $Bcolor = ImageColorAllocate($blurColImg, $bcols[0],$bcols[1],$bcols[2]);
+ ImageFilledRectangle($blurColImg, 0, 0, $w, $h, $Bcolor);
+ $this->ImageWrite($blurColImg, $fileColor);
ImageDestroy($blurColImg);
// The mask is made: BlurTextImage
- $blurTextImg = imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
- ImageColorAllocate($blurTextImg, 0,0,0); // black background
+ $blurTextImg = $this->imagecreate($w+$blurBorder*2,$h+$blurBorder*2);
+ $Bcolor = ImageColorAllocate($blurTextImg, 0,0,0); // black background
+ ImageFilledRectangle($blurTextImg, 0, 0, $w+$blurBorder*2, $h+$blurBorder*2, $Bcolor);
$txtConf['fontColor'] = 'white';
$blurBordArr = Array($blurBorder,$blurBorder);
$this->makeText($blurTextImg,$txtConf, $this->applyOffset($workArea,$blurBordArr));
- $this->ImageGif($blurTextImg, $fileMask); // dump to temporary file
+ $this->ImageWrite($blurTextImg, $fileMask); // dump to temporary file
ImageDestroy($blurTextImg); // destroy
}
}
- $this->imageMagickExec($fileMask,$fileMask,$command);
+ $this->imageMagickExec($fileMask,$fileMask,$command.' +matte');
- $blurTextImg_tmp = $this->imageCreateFromGif($fileMask); // the mask is loaded again
+ $blurTextImg_tmp = $this->imageCreateFromFile($fileMask); // the mask is loaded again
if ($blurTextImg_tmp) { // if nothing went wrong we continue with the blurred mask
// cropping the border from the mask
- $blurTextImg = imagecreate($w,$h);
+ $blurTextImg = $this->imagecreate($w,$h);
$this->imagecopyresized($blurTextImg, $blurTextImg_tmp, 0, 0, $blurBorder, $blurBorder, $w, $h, $w, $h);
ImageDestroy($blurTextImg_tmp); // Destroy the temporary mask
$this->outputLevels($blurTextImg,0,$high,$this->maskNegate); // reducing levels as the opacity demands
}
- $this->ImageGif($blurTextImg, $fileMask); // Dump the mask again
+ $this->ImageWrite($blurTextImg, $fileMask); // Dump the mask again
ImageDestroy($blurTextImg); // Destroy the mask
// The pictures are combined
- $this->ImageGif($im, $fileMenu); // The main pictures is saved temporarily
+ $this->ImageWrite($im, $fileMenu); // The main pictures is saved temporarily
$this->combineExec($fileMenu,$fileColor,$fileMask,$fileMenu);
- $backIm = $this->imageCreateFromGif($fileMenu); // The main image is loaded again...
+ $backIm = $this->imageCreateFromFile($fileMenu); // The main image is loaded again...
if ($backIm) { // ... and if nothing went wrong we load it onto the old one.
ImageColorTransparent($backIm,-1);
$im = $backIm;
$conf['offset']=$cords[0].','.$cords[1];
$cords = $this->objPosition($conf,$workArea,Array($cords[2],$cords[3]));
$cols=$this->convertColor($conf['color']);
- $this->reduceColors($im,256, 255);
- $tmpColor = ImageColorAllocate($im, $cols[0],$cols[1],$cols[2]);
+ if (!$this->truecolor) {
+ $reduce = t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256);
+ $this->reduceColors($im, $reduce-1, $reduce-2); // If "reduce-1" colors (or more) are used reduce them to "reduce-2"
+ }
+
+ $opacity = 0;
+ if (isset($conf['opacity'])) {
+ // conversion:
+ // PHP 0 = opaque, 127 = transparent
+ // TYPO3 100 = opaque, 0 = transparent
+ $opacity = t3lib_div::intInRange(intval($conf['opacity']), 1, 100, 1);
+ $opacity = abs($opacity - 100);
+ $opacity = round((127 * $opacity) / 100);
+ }
+
+ $tmpColor = ImageColorAllocateAlpha($im, $cols[0],$cols[1],$cols[2], $opacity);
imagefilledrectangle($im, $cords[0], $cords[1], $cords[0]+$cords[2]-1, $cords[1]+$cords[3]-1, $tmpColor);
}
$conf['offset']=$cords[0].','.$cords[1];
$cords = $this->objPosition($conf,$this->workArea,Array($cords[2],$cords[3]));
- $newIm = imagecreate($cords[2],$cords[3]);
+ $newIm = $this->imagecreate($cords[2],$cords[3]);
$cols=$this->convertColor($conf['backColor']?$conf['backColor']:$this->setup['backColor']);
- ImageColorAllocate($newIm, $cols[0],$cols[1],$cols[2]);
+ $Bcolor = ImageColorAllocate($newIm, $cols[0],$cols[1],$cols[2]);
+ ImageFilledRectangle($newIm, 0, 0, $cords[2], $cords[3], $Bcolor);
$newConf = Array();
$workArea = Array(0,0,$cords[2],$cords[3]);
if ($conf['width'] || $conf['height'] || $conf['params']) {
$tmpStr = $this->randomName();
$theFile = $tmpStr.'.'.$this->gifExtension;
- $this->ImageGif($im, $theFile);
+ $this->ImageWrite($im, $theFile);
$theNewFile = $this->imageMagickConvert($theFile,$this->gifExtension,$conf['width'],$conf['height'],$conf['params'],'','');
- $tmpImg = $this->imageCreateFromGif($theNewFile[3]);
+ $tmpImg = $this->imageCreateFromFile($theNewFile[3]);
if ($tmpImg) {
ImageDestroy($im);
$im = $tmpImg;
}
/**
- * Reduce colors in image
+ * Reduce colors in image dependend on the actual amount of colors (Only works if we are not in truecolor mode)
*
* @param integer GDlib Image Pointer
* @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.
* @return void
*/
function reduceColors(&$im,$limit, $cols) {
- if (ImageColorsTotal($im)>=$limit) {
+ if (!$this->truecolor && ImageColorsTotal($im)>=$limit) {
$this->makeEffect($im, Array('value'=>'colors='.$cols) );
}
}
-
-
-
-
-
-
-
+ /**
+ * Reduce colors in image using IM and create a palette based image if possible (<=256 colors)
+ *
+ * @param string Image file to reduce
+ * @param integer Number of colors to reduce the image to.
+ * @return string Reduced file
+ */
+ function IMreduceColors($file, $cols) {
+ $fI = t3lib_div::split_fileref($file);
+ $ext = strtolower($fI['fileext']);
+ $result = $this->randomName().'.'.$ext;
+ if (($reduce = t3lib_div::intInRange($cols, 0, ($ext=='gif'?256:$this->truecolorColors), 0))>0) {
+ $params = ' -colors '.$reduce;
+ if (!$this->im_version_4) {
+ // IM4 doesn't have this options but forces them automatically if applicaple (<256 colors in image)
+ if ($reduce<=256) { $params .= ' -type Palette'; }
+ if ($ext=='png' && $reduce<=256) { $prefix = 'png8:'; }
+ }
+ $this->imageMagickExec($file, $prefix.$result, $params);
+ if ($result) {
+ return $result;
+ }
+ }
+ return '';
+ }
*/
function prependAbsolutePath($fontFile) {
$absPath = defined('PATH_typo3') ? dirname(PATH_thisScript).'/' :PATH_site;
- $fontFile = t3lib_div::isAbsPath($fontFile) ? $fontFile : $absPath.$fontFile;
+ $fontFile = t3lib_div::isAbsPath($fontFile) ? $fontFile : t3lib_div::resolveBackPath($absPath.$fontFile);
return $fontFile;
}
// Finding the RGB definitions of the color:
$string=$cParts[0];
if (strstr($string,'#')) {
- $string = ereg_replace('[^A-Fa-f0-9]*','',$string);
+ $string = preg_replace('/[^A-Fa-f0-9]*/','',$string);
$col[]=HexDec(substr($string,0,2));
$col[]=HexDec(substr($string,2,2));
$col[]=HexDec(substr($string,4,2));
} elseif (strstr($string,',')) {
- $string = ereg_replace('[^,0-9]*','',$string);
+ $string = preg_replace('/[^,0-9]*/','',$string);
$strArr = explode(',',$string);
$col[]=intval($strArr[0]);
$col[]=intval($strArr[1]);
$string = $this->csConvObj->utf8_encode($string,$this->nativeCharset); // Convert to UTF-8
}
- // Recode string accoding to TTFLocaleConv. Depreciated.
+ // Recode string accoding to TTFLocaleConv. Deprecated.
if ($this->TTFLocaleConv) {
- $string = recode_string($this->TTFLocaleConv,$string);
+ list($from, $to) = t3lib_div::trimExplode('..', $this->TTFLocaleConv, true);
+ $string = $this->csConvObj->conv($string, $from, $to);
}
return $string;
/**
* Split a string into an array of individual characters
- * 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.
+ * 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.
*
* @param string The text string to split
* @param boolean Return Unicode numbers instead of chars.
// if no convertion should be performed
$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....
- if ($wh_noscale && !$params && !$frame && $newExt==$info[2] && !$mustCreate) {
+ if ($wh_noscale && !$data['crs'] && !$params && !$frame && $newExt==$info[2] && !$mustCreate) {
$info[3] = $imagefile;
return $info;
}
$info[0]=$data[0];
$info[1]=$data[1];
- $frame = $this->noFramePrepended ? '' : '['.intval($frame).']';
+ $frame = $this->noFramePrepended ? '' : intval($frame);
if (!$params) {
$params = $this->cmds[$newExt];
}
+ // Cropscaling:
+ if ($data['crs']) {
+ if (!$data['origW']) { $data['origW'] = $data[0]; }
+ if (!$data['origH']) { $data['origH'] = $data[1]; }
+ $offsetX = intval(($data[0] - $data['origW']) * ($data['cropH']+100)/200);
+ $offsetY = intval(($data[1] - $data['origH']) * ($data['cropV']+100)/200);
+ $params .= ' -crop '.$data['origW'].'x'.$data['origH'].'+'.$offsetX.'+'.$offsetY.' ';
+ }
+
$command = $this->scalecmd.' '.$info[0].'x'.$info[1].'! '.$params.' ';
+ $cropscale = ($data['crs'] ? 'crs-V'.$data['cropV'].'H'.$data['cropH'] : '');
if ($this->alternativeOutputKey) {
- $theOutputName = t3lib_div::shortMD5($command.basename($imagefile).$this->alternativeOutputKey.$frame);
+ $theOutputName = t3lib_div::shortMD5($command.$cropscale.basename($imagefile).$this->alternativeOutputKey.'['.$frame.']');
} else {
- $theOutputName = t3lib_div::shortMD5($command.$imagefile.filemtime($imagefile).$frame);
+ $theOutputName = t3lib_div::shortMD5($command.$cropscale.$imagefile.filemtime($imagefile).'['.$frame.']');
}
if ($this->imageMagickConvert_forceFileNameBody) {
$theOutputName = $this->imageMagickConvert_forceFileNameBody;
// Register temporary filename:
$GLOBALS['TEMP_IMAGES_ON_PAGE'][] = $output;
- if (!$this->file_exists_typo3temp_file($output,$imagefile) || $this->dontCheckForExistingTempFile) {
- $this->imageMagickExec($imagefile.$frame,$output,$command);
+ if ($this->dontCheckForExistingTempFile || !$this->file_exists_typo3temp_file($output, $imagefile)) {
+ $this->imageMagickExec($imagefile, $output, $command, $frame);
}
- if (@file_exists($output)) {
+ if (file_exists($output)) {
$info[3] = $output;
$info[2] = $newExt;
- if ($params) { // params could realisticly change som imagedata!
+ if ($params) { // params could realisticly change some imagedata!
$info=$this->getImageDimensions($info[3]);
}
if ($info[2]==$this->gifExtension && !$this->dontCompress) {
* @see imageMagickConvert(), tslib_cObj::getImgResource()
*/
function getImageDimensions($imageFile) {
- ereg('([^\.]*)$',$imageFile,$reg);
- if (@file_exists($imageFile) && t3lib_div::inList($this->imageFileExt,strtolower($reg[0]))) {
+ preg_match('/([^\.]*)$/',$imageFile,$reg);
+ if (file_exists($imageFile) && t3lib_div::inList($this->imageFileExt,strtolower($reg[0]))) {
if ($returnArr = $this->getCachedImageDimensions($imageFile)) {
return $returnArr;
} else {
*
* @param array $identifyResult: Result of the getImageDimensions function
* @return boolean True if operation was successful
- * @author Michael Stucki <mundaun@gmx.ch> / Robert Lemke <rl@robertlemke.de>
+ * @author Michael Stucki <michael@typo3.org> / Robert Lemke <rl@robertlemke.de>
*/
function cacheImageDimensions($identifyResult) {
global $TYPO3_DB;
// Create a md5 hash of the filename
- if (function_exists('md5_file')) {
- $md5Hash = md5_file($identifyResult[3]);
- } else {
- $md5Hash = md5 (t3lib_div::getURL($identifyResult[3]));
- }
+ $md5Hash = md5_file($identifyResult[3]);
if ($md5Hash) {
$fieldArr = array (
'md5hash' => $md5Hash,
'md5filename' => md5($identifyResult[3]),
- 'tstamp' => time(),
+ 'tstamp' => $GLOBALS['EXEC_TIME'],
'filename' => $identifyResult[3],
'imagewidth' => $identifyResult[0],
'imageheight' => $identifyResult[1],
*
* @param string The image filepath
* @return array Returns an array where [0]/[1] is w/h, [2] is extension and [3] is the filename.
- * @author Michael Stucki <mundaun@gmx.ch> / Robert Lemke <rl@robertlemke.de>
+ * @author Michael Stucki <michael@typo3.org> / Robert Lemke <rl@robertlemke.de>
*/
function getCachedImageDimensions($imageFile) {
global $TYPO3_DB;
// Create a md5 hash of the filename
- if(function_exists('md5_file')) {
- $md5Hash = md5_file($imageFile);
- } else {
- $md5Hash = md5(t3lib_div::getURL ($imageFile));
- }
- ereg('([^\.]*)$',$imageFile,$reg);
- $res = $TYPO3_DB->exec_SELECTquery ('md5hash, imagewidth, imageheight', 'cache_imagesizes', 'md5filename="'.md5($imageFile).'"');
+ $md5Hash = md5_file($imageFile);
+ preg_match('/([^\.]*)$/',$imageFile,$reg);
+ $res = $TYPO3_DB->exec_SELECTquery ('md5hash, imagewidth, imageheight', 'cache_imagesizes', 'md5filename='.$TYPO3_DB->fullQuoteStr(md5($imageFile),'cache_imagesizes'));
if ($res) {
if ($row = $TYPO3_DB->sql_fetch_assoc($res)) {
if ($row['md5hash']!=$md5Hash) {
// file has changed, delete the row
- $TYPO3_DB->exec_DELETEquery ('cache_imagesizes', 'md5hash="'.$TYPO3_DB->quoteStr($row['md5hash'], 'cache_imagesizes').'"');
+ $TYPO3_DB->exec_DELETEquery ('cache_imagesizes', 'md5hash='.$TYPO3_DB->fullQuoteStr($row['md5hash'],'cache_imagesizes'));
} else {
- return (array($row['imagewidth'], $row['imageheight'], strtolower($reg[0]), $imageFile));
+ return (array((int) $row['imagewidth'], (int) $row['imageheight'], strtolower($reg[0]), $imageFile));
}
}
}
*/
function getImageScale($info,$w,$h,$options) {
if (strstr($w.$h, 'm')) {$max=1;} else {$max=0;}
+
+ if (strstr($w.$h, 'c')) {
+ $out['cropH'] = intval(substr(strstr($w, 'c'), 1));
+ $out['cropV'] = intval(substr(strstr($h, 'c'), 1));
+ $crs = true;
+ } else {
+ $crs = false;
+ }
+ $out['crs'] = $crs;
+
$w=intval($w);
$h=intval($h);
// if there are max-values...
$w = round($h*$ratio);
}
}
+ if ($crs) {
+ $ratio = $info[0] / $info[1];
+ if ($h * $ratio < $w) {
+ $h = round($w / $ratio);
+ } else {
+ $w = round($h * $ratio);
+ }
+ }
$info[0] = $w;
$info[1] = $h;
}
$out[1]=$info[1];
// Set minimum-measures!
if ($options['minW'] && $out[0]<$options['minW']) {
- if ($max && $out[0]) {
+ if (($max || $crs) && $out[0]) {
$out[1]= round($out[1]*$options['minW']/$out[0]);
}
$out[0]=$options['minW'];
}
if ($options['minH'] && $out[1]<$options['minH']) {
- if ($max && $out[1]) {
+ if (($max || $crs) && $out[1]) {
$out[0]= round($out[0]*$options['minH']/$out[1]);
}
$out[1]=$options['minH'];
*/
function file_exists_typo3temp_file($output,$orig='') {
if ($this->enable_typo3temp_db_tracking) {
- if (@file_exists($output)) { // If file exists, then we return immediately
+ if (file_exists($output)) { // If file exists, then we return immediately
return 1;
} else { // If not, we look up in the cache_typo3temp_log table to see if there is a image being rendered right now.
$md5Hash=md5($output);
- $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('md5hash', 'cache_typo3temp_log', 'md5hash="'.$GLOBALS['TYPO3_DB']->quoteStr($md5Hash, 'cache_typo3temp_log').'" AND tstamp>'.(time()-30));
+ $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+ 'md5hash',
+ 'cache_typo3temp_log',
+ 'md5hash=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log') . ' AND tstamp>' . ($GLOBALS['EXEC_TIME'] - 30)
+ );
if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) { // If there was a record, the image is being generated by another proces (we assume)
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...)
if (is_object($GLOBALS['TT'])) $GLOBALS['TT']->setTSlogMessage('typo3temp_log: Assume this file is being rendered now: '.$output);
$insertFields = array(
'md5hash' => $md5Hash,
- 'tstamp' => time(),
+ 'tstamp' => $GLOBALS['EXEC_TIME'],
'filename' => $output,
'orig_filename' => $orig
);
- $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_typo3temp_log', 'md5hash="'.$GLOBALS['TYPO3_DB']->quoteStr($md5Hash, 'cache_typo3temp_log').'"');
+ $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_typo3temp_log', 'md5hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($md5Hash, 'cache_typo3temp_log'));
$GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_typo3temp_log', $insertFields);
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);
}
}
} else {
- return @file_exists($output);
+ return file_exists($output);
}
}
function imageMagickIdentify($imagefile) {
if (!$this->NO_IMAGE_MAGICK) {
$frame = $this->noFramePrepended?'':'[0]';
- $cmd = $this->imageMagickPath.'identify '.$this->wrapFileName($imagefile).$frame;
+ $cmd = t3lib_div::imageMagickCommand('identify', $this->wrapFileName($imagefile).$frame);
+ $returnVal = array();
exec($cmd, $returnVal);
$splitstring=$returnVal[0];
$this->IM_commands[] = Array ('identify',$cmd,$returnVal[0]);
if ($splitstring) {
- ereg('([^\.]*)$',$imagefile,$reg);
+ preg_match('/([^\.]*)$/',$imagefile,$reg);
$splitinfo = explode(' ', $splitstring);
while (list($key,$val) = each($splitinfo)) {
$temp = '';
* @param string The relative (to PATH_site) image filepath, input file (read from)
* @param string The relative (to PATH_site) image filepath, output filename (written to)
* @param string ImageMagick parameters
+ * @param integer Optional, 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...
* @return string The result of a call to PHP function "exec()"
*/
- function imageMagickExec($input,$output,$params) {
- if (!$this->NO_IMAGE_MAGICK) {
- $cmd = $this->imageMagickPath.'convert '.$params.' '.$this->wrapFileName($input).' '.$this->wrapFileName($output);
- $this->IM_commands[] = Array ($output,$cmd);
- return exec($cmd);
+ function imageMagickExec($input, $output, $params, $frame = 0) {
+ if (!$this->NO_IMAGE_MAGICK) {
+
+ // Unless noFramePrepended is set in the Install Tool, a frame number is added to
+ // select a specific page of the image (by default this will be the first page)
+ if (!$this->noFramePrepended) {
+ $frame = '[' . intval($frame) . ']';
+ } else {
+ $frame = '';
+ }
+
+ $cmd = t3lib_div::imageMagickCommand('convert', $params . ' ' . $this->wrapFileName($input) . $frame . ' ' . $this->wrapFileName($output));
+ $this->IM_commands[] = array($output,$cmd);
+
+ $ret = exec($cmd);
+ t3lib_div::fixPermissions($output); // Change the permissions of the file
+
+ return $ret;
}
}
* @param string The relative (to PATH_site) image filepath, overlay file (top)
* @param string The relative (to PATH_site) image filepath, the mask file (grayscale)
* @param string The relative (to PATH_site) image filepath, output filename (written to)
+ * @param [type] $handleNegation: ...
* @return void
*/
- function combineExec($input,$overlay,$mask,$output) {
+ function combineExec($input,$overlay,$mask,$output, $handleNegation = false) {
if (!$this->NO_IMAGE_MAGICK) {
- $cmd = $this->imageMagickPath.$this->combineScript.' -compose over '.$this->wrapFileName($input).' '.$this->wrapFileName($overlay).' '.$this->wrapFileName($mask).' '.$this->wrapFileName($output);
+ $params = '-colorspace GRAY +matte';
+ if ($handleNegation) {
+ if ($this->maskNegate) {
+ $params .= ' '.$this->maskNegate;
+ }
+ }
+ $theMask = $this->randomName().'.'.$this->gifExtension;
+ $this->imageMagickExec($mask, $theMask, $params);
+ $cmd = t3lib_div::imageMagickCommand('combine', '-compose over +matte '.$this->wrapFileName($input).' '.$this->wrapFileName($overlay).' '.$this->wrapFileName($theMask).' '.$this->wrapFileName($output)); // +matte = no alpha layer in output
$this->IM_commands[] = Array ($output,$cmd);
- exec($cmd);
+
+ $ret = exec($cmd);
+ t3lib_div::fixPermissions($output); // Change the permissions of the file
+
+ if (is_file($theMask)) {
+ @unlink($theMask);
+ }
+
+ return $ret;
}
}
/**
- * Wrapping the input filename in double-quotes
+ * Escapes a file name so it can safely be used on the command line.
*
- * @param string Input filename
- * @return string The output wrapped in "" (if there are spaces in the filepath)
- * @access private
+ * @param string $inputName filename to safeguard, must not be empty
+ *
+ * @return string $inputName escaped as needed
*/
- function wrapFileName($inputName) {
- if (strstr($inputName,' ')) {
- $inputName='"'.$inputName.'"';
- }
- return $inputName;
+ protected function wrapFileName($inputName) {
+ return escapeshellarg($inputName);
}
function applyImageMagickToPHPGif(&$im, $command) {
$tmpStr = $this->randomName();
$theFile = $tmpStr.'.'.$this->gifExtension;
- $this->ImageGif($im, $theFile);
+ $this->ImageWrite($im, $theFile);
$this->imageMagickExec($theFile,$theFile,$command);
- $tmpImg = $this->imageCreateFromGif($theFile);
+ $tmpImg = $this->imageCreateFromFile($theFile);
if ($tmpImg) {
ImageDestroy($im);
$im = $tmpImg;
*/
function output($file) {
if ($file) {
- ereg('([^\.]*)$',$file,$reg);
+ $reg = array();
+ preg_match('/([^\.]*)$/',$file,$reg);
$ext=strtolower($reg[0]);
switch($ext) {
- case $this->gifExtension:
- if ($this->ImageGif($this->im, $file)) {
- // ImageMagick operations
- if($this->setup['reduceColors']) {
- $this->imageMagickExec($file,$file,' -colors '.t3lib_div::intInRange($this->setup['reduceColors'],2,255));
- t3lib_div::gif_compress($file,''); // Compress with IM (lzw) or GD (rle) (Workaround for the absence of lzw-compression in GD)
- } else {
- t3lib_div::gif_compress($file, 'IM'); // Compress with IM! (adds extra compression, LZW from ImageMagick) (Workaround for the absence of lzw-compression in GD)
+ case 'gif':
+ case 'png':
+ if ($this->ImageWrite($this->im, $file)) {
+ // ImageMagick operations
+ if ($this->setup['reduceColors'] || (!$this->png_truecolor && $this->truecolor)) {
+ $reduced = $this->IMreduceColors($file, t3lib_div::intInRange($this->setup['reduceColors'], 256, $this->truecolorColors, 256));
+ if ($reduced) {
+ @copy($reduced, $file);
+ @unlink($reduced);
+ }
}
+ t3lib_div::gif_compress($file, 'IM'); // Compress with IM! (adds extra compression, LZW from ImageMagick) (Workaround for the absence of lzw-compression in GD)
}
break;
case 'jpg':
case 'jpeg':
- $tmpStr = $this->randomName();
- $theFile = $tmpStr.'.'.$this->gifExtension;
- if ($this->ImageGif($this->im, $theFile)) {
- // ImageMagick operations
- $operations='';
- if($this->setup['quality']) {
- $operations.=' -quality '.t3lib_div::intInRange($this->setup['quality'],10,100);
- }
- $this->imageMagickExec($theFile,$file,$operations);
- if (!$this->dontUnlinkTempFiles) {
- unlink($theFile);
- }
+ $quality = 0; // Use the default
+ if($this->setup['quality']) {
+ $quality = t3lib_div::intInRange($this->setup['quality'],10,100);
}
+ if ($this->ImageWrite($this->im, $file, $quality));
break;
}
$GLOBALS['TEMP_IMAGES_ON_PAGE'][]=$file;
*
* @param pointer The GDlib image resource pointer
* @param string The filename to write to
- * @return mixed The output of either imageGif or imagePng based on whether the $this->gifExtension was set to "gif" or "png"
+ * @param integer The image quality (for JPEGs)
+ * @return boolean The output of either imageGif, imagePng or imageJpeg based on the filename to write
* @see maskImageOntoImage(), scale(), output()
*/
- function ImageGif($destImg, $theImage) {
+ function ImageWrite($destImg, $theImage, $quality=0) {
imageinterlace ($destImg,0);
- if ($this->gifExtension=='gif') {
- return ImageGif($destImg, $theImage);
+ $ext = strtolower(substr($theImage, strrpos($theImage, '.')+1));
+ $result = FALSE;
+ switch ($ext) {
+ case 'jpg':
+ case 'jpeg':
+ if (function_exists('imageJpeg')) {
+ if ($quality == 0) {
+ $quality = $this->jpegQuality;
+ }
+ $result = imageJpeg($destImg, $theImage, $quality);
+ }
+ break;
+ case 'gif':
+ if (function_exists('imageGif')) {
+ if ($this->truecolor) {
+ imagetruecolortopalette($destImg, true, 256);
+ }
+ $result = imageGif($destImg, $theImage);
+ }
+ break;
+ case 'png':
+ if (function_exists('imagePng')) {
+ $result = ImagePng($destImg, $theImage);
+ }
+ break;
}
- if ($this->gifExtension=='png') {
- return ImagePng($destImg, $theImage);
+ if ($result) {
+ t3lib_div::fixPermissions($theImage);
}
+ return $result;
+ }
+
+
+
+ /**
+ * Writes the input GDlib image pointer to file. Now just a wrapper to ImageWrite.
+ *
+ * @param pointer The GDlib image resource pointer
+ * @param string The filename to write to
+ * @return mixed The output of either imageGif, imagePng or imageJpeg based on the filename to write
+ * @see imageWrite()
+ * @deprecated since TYPO3 4.0, this function will be removed in TYPO3 4.5.
+ */
+ function imageGif($destImg, $theImage) {
+ t3lib_div::logDeprecatedFunction();
+
+ return $this->imageWrite($destImg, $theImage);
+ }
+
+ /**
+ * This function has been renamed and only exists for providing backwards compatibility.
+ * Please use $this->imageCreateFromFile() instead.
+ *
+ * @param string Image filename
+ * @return pointer Image Resource pointer
+ * @deprecated since TYPO3 4.0, this function will be removed in TYPO3 4.5.
+ */
+ function imageCreateFromGif($sourceImg) {
+ t3lib_div::logDeprecatedFunction();
+
+ return $this->imageCreateFromFile($sourceImg);
}
/**
* @param string Image filename
* @return pointer Image Resource pointer
*/
- function imageCreateFromGif($sourceImg) {
+ function imageCreateFromFile($sourceImg) {
$imgInf = pathinfo($sourceImg);
$ext = strtolower($imgInf['extension']);
-// if ($ext=='gif' && (ImageTypes() & IMG_GIF)) {
- if ($ext=='gif' && function_exists('imagecreatefromgif')) {
- return imageCreateFromGif($sourceImg);
- }
-// if ($ext=='png' && (ImageTypes() & IMG_PNG)) {
- if ($ext=='png' && function_exists('imagecreatefrompng')) {
- return imageCreateFromPng($sourceImg);
- }
-// if (($ext=='jpg' || $ext=='jpeg') && (ImageTypes() & IMG_JPG)) {
- if (($ext=='jpg' || $ext=='jpeg') && function_exists('imagecreatefromjpeg')) {
- return imageCreateFromJpeg($sourceImg);
+ switch ($ext) {
+ case 'gif':
+ if (function_exists('imagecreatefromgif')) {
+ return imageCreateFromGif($sourceImg);
+ }
+ break;
+ case 'png':
+ if (function_exists('imagecreatefrompng')) {
+ return imageCreateFromPng($sourceImg);
+ }
+ break;
+ case 'jpg':
+ case 'jpeg':
+ if (function_exists('imagecreatefromjpeg')) {
+ return imageCreateFromJpeg($sourceImg);
+ }
+ break;
}
// If non of the above:
$i = @getimagesize($sourceImg);
- $im = imagecreate($i[0],$i[1]);
- ImageColorAllocate($im, 128,128,128);
+ $im = $this->imagecreate($i[0],$i[1]);
+ $Bcolor = ImageColorAllocate($im, 128,128,128);
+ ImageFilledRectangle($im, 0, 0, $i[0], $i[1], $Bcolor);
return $im;
}
-}
+ /**
+ * Creates a new GD image resource. Wrapper for imagecreate(truecolor) depended if GD2 is used.
+ *
+ * @param integer Width of image
+ * @param integer Height of image
+ * @return pointer Image Resource pointer
+ */
+ function imagecreate($w, $h) {
+ if($this->truecolor && function_exists('imagecreatetruecolor')) {
+ return imagecreatetruecolor($w, $h);
+ } else {
+ return imagecreate($w, $h);
+ }
+
+ }
+
+ /**
+ * Returns the HEX color value for an RGB color array
+ *
+ * @param array RGB color array
+ * @return string HEX color value
+ */
+ function hexColor($col) {
+ $r = dechex($col[0]);
+ if (strlen($r)<2) { $r = '0'.$r; }
+ $g = dechex($col[1]);
+ if (strlen($g)<2) { $g = '0'.$g; }
+ $b = dechex($col[2]);
+ if (strlen($b)<2) { $b = '0'.$b; }
+ return '#'.$r.$g.$b;
+ }
+
+ /**
+ * Unifies all colors given in the colArr color array to the first color in the array.
+ *
+ * @param pointer Image resource
+ * @param array Array containing RGB color arrays
+ * @param [type] $closest: ...
+ * @return integer The index of the unified color
+ */
+ function unifyColors(&$img, $colArr, $closest = false) {
+ $retCol = -1;
+ if (is_array($colArr) && count($colArr) && function_exists('imagepng') && function_exists('imagecreatefrompng')) {
+ $firstCol = array_shift($colArr);
+ $firstColArr = $this->convertColor($firstCol);
+ if (count($colArr)>1) {
+ $origName = $preName = $this->randomName().'.png';
+ $postName = $this->randomName().'.png';
+ $this->imageWrite($img, $preName);
+ $firstCol = $this->hexColor($firstColArr);
+ foreach ($colArr as $transparentColor) {
+ $transparentColor = $this->convertColor($transparentColor);
+ $transparentColor = $this->hexColor($transparentColor);
+ $cmd = '-fill "'.$firstCol.'" -opaque "'.$transparentColor.'"';
+ $this->imageMagickExec($preName, $postName, $cmd);
+ $preName = $postName;
+ }
+ $this->imageMagickExec($postName, $origName, '');
+ if (@is_file($origName)) {
+ $tmpImg = $this->imageCreateFromFile($origName);
+ }
+ } else {
+ $tmpImg = $img;
+ }
+ if ($tmpImg) {
+ $img = $tmpImg;
+ if ($closest) {
+ $retCol = ImageColorClosest ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]);
+ } else {
+ $retCol = ImageColorExact ($img, $firstColArr[0], $firstColArr[1], $firstColArr[2]);
+ }
+ }
+ // unlink files from process
+ if (!$this->dontUnlinkTempFiles) {
+ if ($origName) {
+ @unlink($origName);
+ }
+ if ($postName) {
+ @unlink($postName);
+ }
+ }
+ }
+ return $retCol;
+ }
+
+
+}
+
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_stdgraphic.php']);
}
+
?>
\ No newline at end of file