Code: Alles auswählen
<?php
/*****************************************
* File      :   $RCSfile: functions.api.images.php,v $
* Project   :   Contenido
* Descr     :   Contenido Image API functions
*
* Author    :   Timo A. Hummel
*               
* Created   :   08.08.2003
* Modified  :   $Date: 2006/10/05 23:50:41 $
*
* © four for business AG, www.4fb.de
*
* $Id: functions.api.images.php,v 1.41 2006/10/05 23:50:41 bjoern.behrens Exp $
******************************************/
/* Info:
 * This file contains Contenido Image API functions.
 *
 * If you are planning to add a function, please make sure that:
 * 1.) The function is in the correct place
 * 2.) The function is documented
 * 3.) The function makes sense and is generically usable
 *
 */
 
 
/**
 * capiImgScaleGetMD5CacheFile: Returns the MD5 Filename used
 * for caching.
 *
 * @return string Path to the resulting image
 */
function capiImgScaleGetMD5CacheFile ($sImg, $iMaxX, $iMaxY, $bCrop, $bExpand)
{
	if (!file_exists($sImg))
	{
		return false;	
	}
	
	$iFilesize = filesize($sImg);
	
	if (function_exists("md5_file"))
	{
		$sMD5 = md5(implode("", array(
					$sImg,
					md5_file($sImg),
					$iFilesize,
					$iMaxX,
					$iMaxY,
					$bCrop,
					$bExpand)));
	} else {
		$sMD5 = md5(implode("", array(
					$sImg,
					$iFilesize,
					$iMaxX,
					$iMaxY,
					$bCrop,
					$bExpand)));		
	}
	
	return $sMD5;
}
/**
 * capiImgScaleLQ: Scales (or crops) an image.
 * If scaling, the aspect ratio is maintained.
 *
 * Returns the path to the scaled temporary image.
 *
 * Note that this function does some very poor caching;
 * it calculates an md5 hash out of the image plus the
 * maximum X and Y sizes, and uses that as the file name.
 * If the file is older than 10 minutes, regenerate it.
 *
 * @param $img string The path to the image (relative to the frontend)
 * @param $maxX int The maximum size in x-direction
 * @param $maxY int The maximum size in y-direction
 * @param $crop boolean If true, the image is cropped and not scaled.
 * @param $expand boolean If true, the image is expanded (e.g. really scaled).
 *                        If false, the image will only be made smaller. 
 * @param $cacheTime int The number of minutes to cache the image  
 *
 * @return string Path to the resulting image
 */
function capiImgScaleLQ ($img, $maxX, $maxY, $crop = false, $expand = false, $cacheTime = 10)
{
	global $cfgClient, $lang, $client;
	$filename = $img;
	$defaultCacheTime = $cacheTime;
	
	$filetype = substr($filename, strlen($filename) -4,4);
	$filesize = filesize($img);
	$md5 = capiImgScaleGetMD5CacheFile($img, $maxX, $maxY, $crop, $expand);
	
	/* Create the target file names for web and server */
	$cfileName = $md5.".jpg";
	$cacheFile = $cfgClient[$client]["path"]["frontend"]."cache/".$cfileName;
	$webFile = $cfgClient[$client]["path"]["htmlpath"]."cache/".$cfileName;
	
	/* Check if the file exists. If it does, check if the file is valid. */
	if (file_exists($cacheFile))
	{
		if (!function_exists("md5_file"))
		{
			if ((filemtime($cacheFile) + (60 * $defaultCacheTime)) < time())
			{
				/* Cache time expired, unlink the file */
				unlink($cacheFile);	
			} else {
				/* Return the web file name */
				return $webFile;
			}
		} else {
			return $webFile;	
		}
	}
	
	/* Get out which file we have */
	switch (strtolower($filetype))
	{
		case ".gif": $function = "imagecreatefromgif"; break;
		case ".png": $function = "imagecreatefrompng"; break;
		case ".jpg": $function = "imagecreatefromjpeg"; break;
		case "jpeg": $function = "imagecreatefromjpeg"; break;
		default: return false;
	}
	
	if (function_exists($function))
	{
		$imageHandle = @$function($filename);
	}
	
	/* If we can't open the image, return false */
	if (!$imageHandle)
	{
		return false;
	}
	$x = imagesx($imageHandle);
	$y = imagesy($imageHandle);
	
	/* Calculate the aspect ratio */	
	$aspectXY = $x / $y;
	$aspectYX = $y / $x;
	
	if (($maxX / $x) < ($maxY / $y))
	{
		$targetY = $y * ($maxX / $x);
		$targetX = round($maxX);
		
		// force wished height
		if ($targetY < $maxY)
		{
			$targetY = ceil($targetY);
		} else
		{
			$targetY = floor($targetY);
		}
		
	} else {
		$targetX = $x * ($maxY / $y);
		$targetY = round($maxY);
		
		// force wished width
		if ($targetX < $maxX)
		{
			$targetX = ceil($targetX);
		} else
		{
			$targetX = floor($targetX);
		}
	}
	if ($expand == false && (($targetX > $x) || ($targetY > $y)))
	{
		$targetX = $x;
		$targetY = $y;	
	}
	$targetX = ($targetX != 0) ? $targetX : 1;
   	$targetY = ($targetY != 0) ? $targetY : 1;
   	
	/* Create the target image with the target size, resize it afterwards. */
   if ($crop)
   {
      /* Create the target image with the max size, crop it afterwards. */
      $targetImage = imagecreate($maxX, $maxY);
      imagecopy($targetImage, $imageHandle, 0, 0, 0, 0, $maxX, $maxY);
   } else {
      /* Create the target image with the target size, resize it afterwards. */
      $targetImage = imagecreate($targetX, $targetY);
      imagecopyresized($targetImage, $imageHandle, 0, 0, 0, 0, $targetX, $targetY, $x, $y);
   }
	
	/* Output the file */
	imagejpeg($targetImage, $cacheFile);
	
	return ($webFile);
}
/**
 * capiImgScaleHQ: Scales (or crops) an image in high quality.
 * If scaling, the aspect ratio is maintained.
 *
 * Note: GDLib 2.x is required!
 *
 * Returns the path to the scaled temporary image.
 *
 * Note that this function does some very poor caching;
 * it calculates an md5 hash out of the image plus the
 * maximum X and Y sizes, and uses that as the file name.
 * If the file is older than the specified cache time, regenerate it.
 *
 * @param $img string The path to the image (relative to the frontend)
 * @param $maxX int The maximum size in x-direction
 * @param $maxY int The maximum size in y-direction
 * @param $crop boolean If true, the image is cropped and not scaled.
 * @param $cacheTime int The number of minutes to cache the image  
 *
 * @return string Path to the resulting image
 */
function capiImgScaleHQ ($img, $maxX, $maxY, $crop = false, $expand = false, $cacheTime = 10)
{
	global $cfgClient, $lang, $client;
	$filename = $img;
	$defaultCacheTime = $cacheTime;
	
	$filetype = substr($filename, strlen($filename) -4,4);
	$filesize = filesize($img);
	$md5 = capiImgScaleGetMD5CacheFile($img, $maxX, $maxY, $crop, $expand);
	
	/* Create the target file names for web and server */
	$cfileName = $md5.".jpg";
	$cacheFile = $cfgClient[$client]["path"]["frontend"]."cache/".$cfileName;
	$webFile = $cfgClient[$client]["path"]["htmlpath"]."cache/".$cfileName;
	
	/* Check if the file exists. If it does, check if the file is valid. */
	if (file_exists($cacheFile))
	{
		if (!function_exists("md5_file"))
		{
			if ((filemtime($cacheFile) + (60 * $defaultCacheTime)) < time())
			{
				/* Cache time expired, unlink the file */
				unlink($cacheFile);	
			} else {
				/* Return the web file name */
				return $webFile;
			}
		} else {
			return $webFile;	
		}
	}
	
	/* Get out which file we have */
	switch (strtolower($filetype))
	{
		case ".gif": $function = "imagecreatefromgif"; break;
		case ".png": $function = "imagecreatefrompng"; break;
		case ".jpg": $function = "imagecreatefromjpeg"; break;
		case "jpeg": $function = "imagecreatefromjpeg"; break;
		default: return false;
	}
	
	if (function_exists($function))
	{
		$imageHandle = @$function($filename); 
	}
	
	/* If we can't open the image, return false */
	if (!$imageHandle)
	{
		return false;
	}
	$x = imagesx($imageHandle);
	$y = imagesy($imageHandle);
	/* Calculate the aspect ratio */	
	$aspectXY = $x / $y;
	$aspectYX = $y / $x;
	
	if (($maxX / $x) < ($maxY / $y))
	{
		$targetY = $y * ($maxX / $x);
		$targetX = round($maxX);
		
		// force wished height
		if ($targetY < $maxY)
		{
			$targetY = ceil($targetY);
		} else
		{
			$targetY = floor($targetY);
		}
		
	} else {
		$targetX = $x * ($maxY / $y);
		$targetY = round($maxY);
		
		// force wished width
		if ($targetX < $maxX)
		{
			$targetX = ceil($targetX);
		} else
		{
			$targetX = floor($targetX);
		}
	}
	
	if ($expand == false && (($targetX > $x) || ($targetY > $y)))
	{
		$targetX = $x;
		$targetY = $y;	
	}	
	$targetX = ($targetX != 0) ? $targetX : 1;
   	$targetY = ($targetY != 0) ? $targetY : 1;
   	
	/* Create the target image with the target size, resize it afterwards. */
if ($crop)
   {
      /* Create the target image with the max size, crop it afterwards. */
      $targetImage = imagecreatetruecolor($maxX, $maxY);
      imagecopy($targetImage, $imageHandle, 0, 0, 0, 0, $maxX, $maxY);
   } else {
      /* Create the target image with the target size, resize it afterwards. */
      $targetImage = imagecreatetruecolor($targetX, $targetY);
      imagecopyresampled($targetImage, $imageHandle, 0, 0, 0, 0, $targetX, $targetY, $x, $y);
   }
	
	/* Output the file */
	imagejpeg($targetImage, $cacheFile);
	
	return ($webFile);
}
/**
 * capiImgScaleImageMagick: Scales (or crops) an image using ImageMagick.
 * If scaling, the aspect ratio is maintained.
 *
 * Note: ImageMagick is required!
 *
 * Returns the path to the scaled temporary image.
 *
 * Note that this function does some very poor caching;
 * it calculates an md5 hash out of the image plus the
 * maximum X and Y sizes, and uses that as the file name.
 * If the file is older than the specified cache time, regenerate it.
 *
 * @param $img string The path to the image (relative to the frontend)
 * @param $maxX int The maximum size in x-direction
 * @param $maxY int The maximum size in y-direction
 * @param $crop boolean If true, the image is cropped and not scaled.
 * @param $cacheTime int The number of minutes to cache the image  
 *
 * @return string Path to the resulting image
 */
function capiImgScaleImageMagick ($img, $maxX, $maxY, $crop = false, $expand = false, $cacheTime = 10)
{
	global $cfgClient, $lang, $client;
	$filename = $img;
	$defaultCacheTime = $cacheTime;
	
	$filetype = substr($filename, strlen($filename) -4,4);
	$filesize = filesize($img);
	$md5 = capiImgScaleGetMD5CacheFile($img, $maxX, $maxY, $crop, $expand);
	
	/* Create the target file names for web and server */
	$cfileName = $md5.".jpg";
	$cacheFile = $cfgClient[$client]["path"]["frontend"]."cache/".$cfileName;
	$webFile = $cfgClient[$client]["path"]["htmlpath"]."cache/".$cfileName;
	
	/* Check if the file exists. If it does, check if the file is valid. */
	if (file_exists($cacheFile))
	{
		if (!function_exists("md5_file"))
		{
			if ((filemtime($cacheFile) + (60 * $defaultCacheTime)) < time())
			{
				/* Cache time expired, unlink the file */
				unlink($cacheFile);	
			} else {
				/* Return the web file name */
				return $webFile;
			}
		} else {
			return $webFile;	
		}
	}
	list($x, $y) = getimagesize($filename);	
	/* Calculate the aspect ratio */	
	$aspectXY = $x / $y;
	$aspectYX = $y / $x;
	
	if (($maxX / $x) < ($maxY / $y))
	{
		$targetY = $y * ($maxX / $x);
		$targetX = round($maxX);
		
		// force wished height
		if ($targetY < $maxY)
		{
			$targetY = ceil($targetY);
		} else
		{
			$targetY = floor($targetY);
		}
		
	} else {
		$targetX = $x * ($maxY / $y);
		$targetY = round($maxY);
		
		// force wished width
		if ($targetX < $maxX)
		{
			$targetX = ceil($targetX);
		} else
		{
			$targetX = floor($targetX);
		}
	}
	
	if ($expand == false && (($targetX > $x) || ($targetY > $y)))
	{
		$targetX = $x;
		$targetY = $y;	
	}
	
	$targetX = ($targetX != 0) ? $targetX : 1;
   	$targetY = ($targetY != 0) ? $targetY : 1;	
	// if is animated gif resize first frame
	if ($filetype == ".gif")
    {
		if (isAnimGif($filename))
        {
			$filename .= "[0]";
        }
    }
	/* Try to execute convert */
	$output = array();
	$retVal = 0;
	if ($crop)
	{
		exec ("convert -gravity center -quality 75 -crop {$maxX}x{$maxY}+1+1 \"$filename\" $cacheFile", $output, $retVal);
	} else {
		exec ("convert -quality 75 -geometry {$targetX}x{$targetY} \"$filename\" $cacheFile", $output, $retVal );
	}
	if (!file_exists($cacheFile))
	{
		return false;
	}
	
	return ($webFile);
}
/**
 * check if gif is animated
 *
 * @param string file path
 *
 * @return boolean true (gif is animated)/ false (single frame gif)
 */
function isAnimGif($sFile)
{
	$output = array();
	$retval = 0;
	
	exec('identify ' . $sFile, $output, $retval);
	
	if (count($output) == 1)
	{
		return false;
	}
	
	return true;	
}
/**
 * capiImgScale: Scales (or crops) an image.
 * If scaling, the aspect ratio is maintained.
 *
 * This function chooses the best method to scale, depending on
 * the system environment and/or the parameters.
 *
 * Returns the path to the scaled temporary image.
 *
 * Note that this function does some very poor caching;
 * it calculates an md5 hash out of the image plus the
 * maximum X and Y sizes, and uses that as the file name.
 * If the file is older than 10 minutes, regenerate it.
 *
 * @param $img string The path to the image (relative to the frontend)
 * @param $maxX int The maximum size in x-direction
 * @param $maxY int The maximum size in y-direction
 * @param $crop boolean If true, the image is cropped and not scaled.
 * @param $expand boolean If true, the image is expanded (e.g. really scaled).
 *                        If false, the image will only be made smaller. 
 * @param $cacheTime int The number of minutes to cache the image  
 * @param $wantHQ boolean If true, try to force high quality mode
 *
 * @return string Path to the resulting image
 */
function capiImgScale ($img, $maxX, $maxY, $crop = false, $expand = false, $cacheTime = 10, $wantHQ = false)
{
	global $client, $db, $cfg, $cfgClient;
	
	$deleteAfter = false;
    
	$sRelativeImg = str_replace($cfgClient[$client]["upl"]["path"], "", $img);
	if (is_dbfs($sRelativeImg))
	{
		// This check should be faster than a file existance check
		$dbfs = new DBFSCollection;
    			
		$file = basename($sRelativeImg);
    			
		$dbfs->writeToFile($sRelativeImg, $cfgClient[$client]["path"]["frontend"]."cache/".$file);
    			
		$img = $cfgClient[$client]["path"]["frontend"]."cache/".$file;
    	$deleteAfter = true;
	} else if (!file_exists($img))
	{
		/* Try with upload string */
		if (file_exists($cfgClient[$client]["upl"]["path"].$img) && !is_dir($cfgClient[$client]["upl"]["path"].$img))
		{
			$img = $cfgClient[$client]["upl"]["path"].$img;
		} else
		{
    		/* No, it's neither in the upload directory nor in the dbfs. return. */
    		return false;
    	}
	}
	
	$filename = $img;
	$filetype = substr($filename, strlen($filename) -4,4);
	
	$mxdAvImgEditingPosibility= checkImageEditingPosibility();
	switch ($mxdAvImgEditingPosibility)
	{
		case '1': // gd1
			$method = 'gd1';
			if (!function_exists('imagecreatefromgif') && $filetype == '.gif') 
			{
				$method = 'failure';
			}
			break;
		case '2': //gd2
			$method = 'gd2';
			if (!function_exists('imagecreatefromgif') && $filetype == '.gif') 
			{
				$method = 'failure';
			}
			break;
		case 'im': //imagemagick
			$method = 'im';
			break;
		case '0':
			$method = 'failure';
			break;
		default:
			$method = 'failure';
			break;
	}
	
	switch ($method)
	{
		case 'gd1':
			$return = capiImgScaleLQ($img, $maxX, $maxY, $crop, $expand, $cacheTime);	
			break;
		
		case 'gd2':
			$return = capiImgScaleHQ($img, $maxX, $maxY, $crop, $expand, $cacheTime);
			break;
		
		case 'im':
			$return = capiImgScaleImageMagick($img, $maxX, $maxY, $crop, $expand, $cacheTime);
			break;
		
		case 'failure':
        	$return = str_replace($cfgClient[$client]["path"]["frontend"], $cfgClient[$client]["path"]["htmlpath"], $img);
			break;
	}
	
	if ($deleteAfter == true)
	{
		unlink($img);
	}
	
	return $return;
					
}
/**
* check possible image editing functionality
*
* return mixed information about installed image editing extensions/tools
*/
function checkImageEditingPosibility() {
	if (isImageMagickAvailable())
	{
		return 'im';
	} else
	{
		if (extension_loaded('gd'))
		{
			if (function_exists('gd_info'))
			{
				$arrGDInformations = gd_info();
			
				if (preg_match('#([0-9\.])+#', $arrGDInformations['GD Version'], $strGDVersion))
				{
					if ($strGDVersion[0] >= '2')
					{
						return '2';
					}
					return '1';
				}
				return '1';
			}
			return '1';
		}
		return '0';
	}
}
?>