Delay a while loop in PHP to prevent memory exhaustion? - php
I have a pretty simple image resize script that loops through 1000 folders, with different amounts of images in each folder. On my testing server, there aren't a lot of images, so it runs fine...but live with about 100K images...it will run into the memory problem. The php memory is already set to 384M, but i'd rather have the script maybe only process 10 folders at a time, stop for a bit, then start again. How can I do that within the while loop? use the sleep function maybe?
Here it is...
class DevTestHelper {
//This will Go through all full size images and resize images into requested folder
function resizeGalleryImages($destFolder, $width, $height, $isCrop = false) {
$count = 1000;
$source = JPATH_SITE."/images/gallery/full";
$dest = JPATH_SITE."/images/gallery/".$destFolder;
echo 'Processing Images<br>';
//Loop through all 1000 folders 0 to 999 in the /full dir
for($i=0; $i < $count;$i++) {
$iPath = $source.'/'.$i;
if(is_dir($iPath)) {
$h = opendir($iPath);
//Loop through all the files in numbered folder
while ($entry = readdir($h)) {
//only read files
if ($entry != "." && $entry != ".." && !is_dir($entry)) {
$img = new GImage($source.'/'.$i.'/'.$entry);
$tmp = $img->resize($width, $height, true, 3);
if($isCrop) {
$tmpWidth = $tmp->getWidth();
$tmpHeight = $tmp->getHeight();
$xOffset = ($tmpWidth - $width) / 2;
$yOffset = ($tmpHeight - $height) / 2;
$tmp->crop($width, $height, $xOffset, $yOffset, false, 3);
}
$destination = $dest.'/'.$i.'/'.$entry;
if(!$tmp->toFile($destination)) {
echo 'error in creating resized image at: '.$destination.'<br>';
}
flush();
ob_flush();
sleep(10);
echo $entry ;
//echo $entry.'<br>';
}
}
echo 'Processed: '.$i.' Folder<br>';
}
}
Thanks for any suggestions.
/**
* Class to manipulate an image.
*
* #package Gallery.Libraries
* #subpackage Media
* #version 1.0
*/
class GImage extends JObject
{
/**
* The image handle
*
* #access private
* #var resource
*/
var $_handle = null;
/**
* The source image path
*
* #access private
* #var string
*/
var $_path = null;
var $_support = array();
/**
* Constructor
*
* #access public
* #return void
* #since 1.0
*/
function __construct($source=null)
{
// First we test if dependencies are met.
if (!GImageHelper::test()) {
$this->setError('Unmet Dependencies');
return false;
}
// Determine which image types are supported by GD.
$info = gd_info();
if ($info['JPG Support']) {
$this->_support['JPG'] = true;
}
if ($info['GIF Create Support']) {
$this->_support['GIF'] = true;
}
if ($info['PNG Support']) {
$this->_support['PNG'] = true;
}
// If the source input is a resource, set it as the image handle.
if ((is_resource($source) && get_resource_type($source) == 'gd')) {
$this->_handle = &$source;
} elseif (!empty($source) && is_string($source)) {
// If the source input is not empty, assume it is a path and populate the image handle.
//Andy - Big freaking cockroach: if file is wrong type or doesn't even exist the error is not handled.
$this->loadFromFile($source);
}
}
function crop($width, $height, $left, $top, $createNew = true, $scaleMethod = JXIMAGE_SCALE_INSIDE)
{
// Make sure the file handle is valid.
if ((!is_resource($this->_handle) || get_resource_type($this->_handle) != 'gd')) {
$this->setError('Invalid File Handle');
return false;
}
// Sanitize width.
$width = ($width === null) ? $height : $width;
if (preg_match('/^[0-9]+(\.[0-9]+)?\%$/', $width)) {
$width = intval(round($this->getWidth() * floatval(str_replace('%', '', $width)) / 100));
} else {
$width = intval(round(floatval($width)));
}
// Sanitize height.
$height = ($height === null) ? $width : $height;
if (preg_match('/^[0-9]+(\.[0-9]+)?\%$/', $height)) {
$height = intval(round($this->getHeight() * floatval(str_replace('%', '', $height)) / 100));
} else {
$height = intval(round(floatval($height)));
}
// Sanitize left.
$left = intval(round(floatval($left)));
// Sanitize top.
$top = intval(round(floatval($top)));
// Create the new truecolor image handle.
$handle = imagecreatetruecolor($width, $height);
// Allow transparency for the new image handle.
imagealphablending($handle, false);
imagesavealpha($handle, true);
if ($this->isTransparent()) {
// Get the transparent color values for the current image.
$rgba = imageColorsForIndex($this->_handle, imagecolortransparent($this->_handle));
$color = imageColorAllocate($this->_handle, $rgba['red'], $rgba['green'], $rgba['blue']);
// Set the transparent color values for the new image.
imagecolortransparent($handle, $color);
imagefill($handle, 0, 0, $color);
imagecopyresized(
$handle,
$this->_handle,
0, 0,
$left,
$top,
$width,
$height,
$width,
$height
);
} else {
imagecopyresampled(
$handle,
$this->_handle,
0, 0,
$left,
$top,
$width,
$height,
$width,
$height
);
}
// If we are cropping to a new image, create a new GImage object.
if ($createNew)
{
// Create the new GImage object for the new truecolor image handle.
$new = new GImage($handle);
return $new;
} else
{
// Swap out the current handle for the new image handle.
$this->_handle = &$handle;
return true;
}
}
function filter($type)
{
// Initialize variables.
$name = preg_replace('#[^A-Z0-9_]#i', '', $type);
$className = 'GImageFilter_'.ucfirst($name);
if (!class_exists($className))
{
jimport('joomla.filesystem.path');
if ($path = JPath::find(GImageFilter::addIncludePath(), strtolower($name).'.php'))
{
require_once $path;
if (!class_exists($className)) {
$this->setError($className.' not found in file.');
return false;
}
}
else {
$this->setError($className.' not supported. File not found.');
return false;
}
}
$instance = new $className;
if (is_callable(array($instance, 'execute')))
{
// Setup the arguments to call the filter execute method.
$args = func_get_args();
array_shift($args);
array_unshift($args, $this->_handle);
// Call the filter execute method.
$return = call_user_func_array(array($instance, 'execute'), $args);
// If the filter failed, proxy the error and return false.
if (!$return) {
$this->setError($instance->getError());
return false;
}
return true;
}
else {
$this->setError($className.' not valid.');
return false;
}
}
function getHeight()
{
return imagesy($this->_handle);
}
function getWidth()
{
return imagesx($this->_handle);
}
function isTransparent()
{
// Make sure the file handle is valid.
if ((!is_resource($this->_handle) || get_resource_type($this->_handle) != 'gd')) {
$this->setError('Invalid File Handle');
return false;
}
return (imagecolortransparent($this->_handle) >= 0);
}
function loadFromFile($path)
{
// Make sure the file exists.
if (!JFile::exists($path)) {
$this->setError('File Does Not Exist');
return false;
}
// Get the image properties.
$properties = GImageHelper::getProperties($path);
if (!$properties) {
return false;
}
// Attempt to load the image based on the MIME-Type
switch ($properties->get('mime'))
{
case 'image/gif':
// Make sure the image type is supported.
if (empty($this->_support['GIF'])) {
$this->setError('File Type Not Supported');
return false;
}
// Attempt to create the image handle.
$handle = #imagecreatefromgif($path);
if (!is_resource($handle)) {
$this->setError('Unable To Process Image');
return false;
}
$this->_handle = &$handle;
break;
case 'image/jpeg':
// Make sure the image type is supported.
if (empty($this->_support['JPG'])) {
$this->setError('File Type Not Supported');
return false;
}
// Attempt to create the image handle.
$handle = #imagecreatefromjpeg($path);
if (!is_resource($handle)) {
$this->setError('Unable To Process Image');
return false;
}
$this->_handle = &$handle;
break;
case 'image/png':
// Make sure the image type is supported.
if (empty($this->_support['PNG'])) {
$this->setError('File Type Not Supported');
return false;
}
// Attempt to create the image handle.
$handle = #imagecreatefrompng($path);
if (!is_resource($handle)) {
$this->setError('Unable To Process Image');
return false;
}
$this->_handle = &$handle;
break;
default:
$this->setError('File Type Not Supported');
return false;
break;
}
// Set the filesystem path to the source image.
$this->_path = $path;
return true;
}
function resize($width, $height, $createNew = true, $scaleMethod = JXIMAGE_SCALE_INSIDE)
{
// Make sure the file handle is valid.
if ((!is_resource($this->_handle) || get_resource_type($this->_handle) != 'gd')) {
$this->setError('Invalid File Handle');
return false;
}
// Prepare the dimensions for the resize operation.
$dimensions = $this->_prepareDimensions($width, $height, $scaleMethod);
if (empty($dimensions)) {
return false;
}
//var_dump($dimensions);
// Create the new truecolor image handle.
$handle = imagecreatetruecolor($dimensions['width'], $dimensions['height']);
// Allow transparency for the new image handle.
imagealphablending($handle, false);
imagesavealpha($handle, true);
if ($this->isTransparent()) {
// Get the transparent color values for the current image.
$rgba = imageColorsForIndex($this->_handle, imagecolortransparent($this->_handle));
$color = imageColorAllocate($this->_handle, $rgba['red'], $rgba['green'], $rgba['blue']);
// Set the transparent color values for the new image.
imagecolortransparent($handle, $color);
imagefill($handle, 0, 0, $color);
imagecopyresized(
$handle,
$this->_handle,
0, 0, 0, 0,
$dimensions['width'],
$dimensions['height'],
$this->getWidth(),
$this->getHeight()
);
} else {
imagecopyresampled(
$handle,
$this->_handle,
0, 0, 0, 0,
$dimensions['width'],
$dimensions['height'],
$this->getWidth(),
$this->getHeight()
);
}
// If we are resizing to a new image, create a new GImage object.
if ($createNew)
{
// Create the new GImage object for the new truecolor image handle.
$new = new GImage($handle);
return $new;
} else
{
// Swap out the current handle for the new image handle.
$this->_handle = &$handle;
return true;
}
}
function toFile($path, $type = IMAGETYPE_JPEG, $options=array())
{
switch ($type)
{
case IMAGETYPE_GIF:
$ret = imagegif($this->_handle, $path);
break;
case IMAGETYPE_PNG:
$ret = imagepng($this->_handle, $path, (array_key_exists('quality', $options)) ? $options['quality'] : 0);
break;
case IMAGETYPE_JPEG:
default:
$ret = imagejpeg($this->_handle, $path, (array_key_exists('quality', $options)) ? $options['quality'] : 100);
break;
}
return $ret;
}
function display() {
//header('Content-type: image/jpeg');
imagejpeg($this->_handle,'',100);
}
function _prepareDimensions($width, $height, $scaleMethod)
{
// Sanitize width.
$width = ($width === null) ? $height : $width;
if (preg_match('/^[0-9]+(\.[0-9]+)?\%$/', $width)) {
$width = intval(round($this->getWidth() * floatval(str_replace('%', '', $width)) / 100));
} else {
$width = intval(round(floatval($width)));
}
// Sanitize height.
$height = ($height === null) ? $width : $height;
if (preg_match('/^[0-9]+(\.[0-9]+)?\%$/', $height)) {
$height = intval(round($this->getHeight() * floatval(str_replace('%', '', $height)) / 100));
} else {
$height = intval(round(floatval($height)));
}
$dimensions = array();
if ($scaleMethod == JXIMAGE_SCALE_FILL)
{
$dimensions['width'] = $width;
$dimensions['height'] = $height;
}
elseif ($scaleMethod == JXIMAGE_SCALE_INSIDE || $scaleMethod == JXIMAGE_SCALE_OUTSIDE)
{
$rx = $this->getWidth() / $width;
$ry = $this->getHeight() / $height;
if ($scaleMethod == JXIMAGE_SCALE_INSIDE)
$ratio = ($rx > $ry) ? $rx : $ry;
else
$ratio = ($rx < $ry) ? $rx : $ry;
$dimensions['width'] = round($this->getWidth() / $ratio);
$dimensions['height'] = round($this->getHeight() / $ratio);
}
else {
$this->setError('Invalid Fit Option');
return false;
}
return $dimensions;
}
}
class GImageFilter extends JObject
{
/**
* Add a directory where GImage should search for filters. You may
* either pass a string or an array of directories.
*
* #access public
* #param string A path to search.
* #return array An array with directory elements
* #since 1.5
*/
function addIncludePath($path='')
{
static $paths;
if (!isset($paths)) {
$paths = array(dirname(__FILE__).'/image');
}
// force path to array
settype($path, 'array');
// loop through the path directories
foreach ($path as $dir)
{
if (!empty($dir) && !in_array($dir, $paths)) {
array_unshift($paths, JPath::clean( $dir ));
}
}
return $paths;
}
function execute()
{
$this->setError('Method Not Implemented');
return false;
}
}
class GImageHelper
{
function getProperties($path)
{
// Initialize the path variable.
$path = (empty($path)) ? $this->_path : $path;
// Make sure the file exists.
if (!JFile::exists($path)) {
$e = new JException('File Does Not Exist');
return false;
}
// Get the image file information.
$info = #getimagesize($path);
if (!$info) {
$e = new JException('Unable To Get Image Size');
return false;
}
// Build the response object.
$result = new JObject;
$result->set('width', $info[0]);
$result->set('height', $info[1]);
$result->set('type', $info[2]);
$result->set('attributes', $info[3]);
$result->set('bits', #$info['bits']);
$result->set('channels', #$info['channels']);
$result->set('mime', $info['mime']);
return $result;
}
function test()
{
return (function_exists('gd_info') && function_exists('imagecreatetruecolor'));
}
}
It looks to me like you have a memory leak, when creating $img using new GImage it will likely be reading the image into memory which you never release.
You take a copy of the resized image:
$tmp = $img->resize($width, $height, true, 3);
but next time around the loop you create a new GImage again using the $img variable.
Does GIMage have some kind of close or cleanup function? If so, do that at the end of each loop before you call new GImage again.
closeGImage($img);
UPDATE:
In response to your updated question it looks like you can do one of two things:
Change the 3rd parameter of $img->resize() to false as this will stop a new GImage being created on image resize.
Write your own image destroy function as part of the GImage class. Because GImage is based upon the GD library you can use the imagedestroy function, see here.
UPDATE 2:
Ok, so following on from your comment... What you'll want to do to create a destroy image function is inside the GImage class, add the following function:
function closeImage()
{
imagedestroy($this->_handle);
}
Now at the bottom of the for loop in devtest.php add a call to this function:
...
ob_flush();
sleep(10);
echo $entry ;
$img->closeImage();
...
Try using sleep or usleep to avoid CPU overload.
Maybe GImage have a dispose() or destroy() method to avoid memory retention.
You could also do batch processing.
Related
Warning: imagecopy() expects parameter 1 to be resource, null given in /directory/avatar.php on line 72
Wassup fellow coders, i stumbled upon a weird error regarding my Image Layering php script for an avatar on a project i'm working on. Does any of you perhaps know the reason why its giving me an error like that? Because its the first time im seeing this error lol. Here is the code btw: <?php include "MISC/trueconnect.php"; if($_GET['id']){ $id = $_GET['id']; $getUser = $conn->query("SELECT * FROM Users WHERE id='$id'"); } $avatar = $getUser->fetch(PDO::FETCH_OBJ); $Body = $avatar->package; if (empty($Body)) { $Body = "Avatar"; } $BottomID = $avatar->pants; if (empty($BottomID)) { $BottomID = "CharacterBG"; } $ShirtID = $avatar->shirt; if (empty($ShirtID)) { $ShirtID = "CharacterBG"; } $HatID = $avatar->hat; if (empty($HatID)) { $HatID = "CharacterBG"; } $ToolID = $avatar->accessory; if (empty($ToolID)) { $ToolID = "CharacterBG"; } $ScarfID = $avatar->mask; if (empty($ScarfID)) { $ScarfID = "CharacterBG"; } $FaceID = $avatar->face; if (empty($FaceID)) { $ToolID = "CharacterBG"; } class StackImage { private $image; private $width; private $height; public function __construct($Path) { if(!isset($Path) || !file_exists($Path)) return; $this->image = imagecreatefrompng($Path); imagesavealpha($this->image, true); imagealphablending($this->image, true); $this->width = imagesx($this->image); $this->height = imagesy($this->image); } public function AddLayer($Path) { if(!isset($Path) || !file_exists($Path)) return; $new = imagecreatefrompng($Path); imagesavealpha($new, true); imagealphablending($new, true); imagecopy($this->image, $new, 1, 0, 0, 0, imagesx($new), imagesy($new)); } public function Output($type = "image/png") { header("Content-Type: {$type}"); imagepng($this->image); imagedestroy($this->image); } public function GetWidth() { return $this->width; } public function GetHeight() { return $this->height; } } $Image = new StackImage($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/CharacterBG.png"); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$Body); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$FaceID); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$BottomID); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$ShirtID); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$ScarfID); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$ToolID); $Image->AddLayer($_SERVER["DOCUMENT_ROOT"]."/CDN/ITEMS/".$HatID); $Image->Output(); ?> Thanks! ~Grizler
The error says it all. Parameter 1 doesn't get the resource parameter but get's null. Do you also think about why it could be null? You can use print_r($variable) to see if parameter 1 is actually null.
PHP - .png and .gif together issue
I run a website where users can customize their own avatar. They can upload items, like "hats" and "shirts", which can be uploaded as a .png or .gif. Then, the "avatar" is outputted. The code for that is below. However when I "wear" an hat that is a .png, it shows up on my avatar, but if I wear a hat that is a .gif, it doesn't appear. How do I make it so that the avatar outputs .png items and .gif items together? //retrieve user info from request //example: Avatar.php?ID=1 (page will load avatar for user with ID of 1) $ID = $db->real_escape_string(strip_tags(stripslashes($_GET['ID']))); $Username = $db->real_escape_string(strip_tags(stripslashes($_GET['Username']))); if (!$Username) { $getUser = mysqli_query($db, "SELECT * FROM Users WHERE ID='".$ID."'"); } else { $getUser = mysqli_query($db, "SELECT * FROM Users WHERE Username='".$Username."'"); } $gU = mysqli_fetch_object($getUser); //load clothing $Body = $gU->Body; if (empty($Body)) { $Body = "/Avatars/Avatar.png"; } $Background = $gU->Background; if (empty($Background)) { $Background = "thingTransparent.png"; } $Eyes = $gU->Eyes; if (empty($Eyes)) { $Eyes = "thingTransparent.png"; } $Mouth = $gU->Mouth; if (empty($Mouth)) { $Mouth = "thingTransparent.png"; } $Hair = $gU->Hair; if (empty($Hair)) { $Hair = "thingTransparent.png"; } $Bottom = $gU->Bottom; if (empty($Bottom)) { $Bottom = "thingTransparent.png"; } $Top = $gU->Top; if (empty($Top)) { $Top = "thingTransparent.png"; } $TShirt = $gU->TShirt; if (empty($TShirt)) { $TShirt = "thingTransparent.png"; } $Hat3 = $gU->Hat3; if (empty($Hat3)) { $Hat3 = "thingTransparent.png"; } $Hat2 = $gU->Hat2; if (empty($Hat2)) { $Hat2 = "thingTransparent.png"; } $Hat = $gU->Hat; if (empty($Hat)) { $Hat = "thingTransparent.png"; } $Shoes = $gU->Shoes; if (empty($Shoes)) { $Shoes = "thingTransparent.png"; } $Accessory = $gU->Accessory; if (empty($Accessory)) { $Accessory = "thingTransparent.png"; } //render the avatar image class StackImage { private $image; private $width; private $height; public function __construct($Path) { if(!isset($Path) || !file_exists($Path)) return; $this->image = imagecreatefrompng($Path); imagesavealpha($this->image, true); imagealphablending($this->image, true); $this->width = imagesx($this->image); $this->height = imagesy($this->image); } public function AddLayer($Path) { if(!isset($Path) || !file_exists($Path)) return; $new = imagecreatefrompng($Path); imagesavealpha($new, true); imagealphablending($new, true); imagecopy($this->image, $new, 0, 0, 0, 0, imagesx($new), imagesy($new)); } public function Output($type = "image/png") { header("Content-Type: {$type}"); imagepng($this->image); imagedestroy($this->image); } public function GetWidth() { return $this->width; } public function GetHeight() { return $this->height; } } //add layer to image for the items that the user is wearing //must be in specific order so you don't have unnecessary items overlapping each other incorrectly //don't touch the bottom code $Image = new StackImage("Store/Dir/thingTransparent.png"); $Image->AddLayer("Store/Dir/".$Background.""); $Image->AddLayer("Store/Dir/".$Body.""); $Image->AddLayer("Store/Dir/".$Eyes.""); $Image->AddLayer("Store/Dir/".$Mouth.""); $Image->AddLayer("Store/Dir/".$Bottom.""); $Image->AddLayer("Store/Dir/".$Top.""); $Image->AddLayer("Store/Dir/".$TShirt.""); $Image->AddLayer("Store/Dir/".$Hair.""); $Image->AddLayer("Store/Dir/".$Hat.""); $Image->AddLayer("Store/Dir/".$Shoes.""); $Image->AddLayer("Store/Dir/".$Accessory.""); //if the user is online, show online symbol if (time() < $gU->expireTime) { $Image->AddLayer("Images/Online.png"); } //or else if the user is offline, show offline symbol else { $Image->AddLayer("Images/Offline.png"); } //if the user is premium, show a little premium icon to the bottom left of their avatar if ($gU->Premium == 1) { $Image->AddLayer("Images/Premium.png"); } //load up the rendered image $Image->Output();
In AddLayer() you might need to change this line $new = imagecreatefrompng($Path); to check whether the source is GIF or PNG and then use the appropriate "imagecreatefrom*() method.
Magento + Imagemagick Proportional Images
Implemented Imagemagick instead of GD2 in Magento 1.7.0.2 as suggested here: http://www.magentocommerce.com/boards/v/viewthread/6158/P135/#t328638 However the new images are not proportional, causing stretching. They were perfect with GD2 Instructions: In the Gd2.php file, in the save() function comment out call_user_func_array($this->_getCallback('output'), $functionParameters); This is the where Magento calls the imagejpeg() function. Yuck. Now add the following code just below the commented out line. $source_file = $this->_fileSrcPath.'/'.$this->_fileSrcName; $image_info = getimagesize($source_file); $im = new Imagick(); $im->readImage($source_file); //check to see if image needs to be resized (eg. thumbnails) if ($image_info[0] != $this->_imageSrcWidth) { $im->thumbnailImage($this->_imageSrcWidth, $this->_imageSrcHeight); } $im->writeImage($fileName); Here is the implemented code <?php /** * Magento * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 3.0) * that is bundled with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://opensource.org/licenses/osl-3.0.php * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license#magentocommerce.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade Magento to newer * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * * #category Varien * #package Varien_Image * #copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * #license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ class Varien_Image_Adapter_Gd2 extends Varien_Image_Adapter_Abstract { protected $_requiredExtensions = Array("gd"); private static $_callbacks = array( IMAGETYPE_GIF => array('output' => 'imagegif', 'create' => 'imagecreatefromgif'), IMAGETYPE_JPEG => array('output' => 'imagejpeg', 'create' => 'imagecreatefromjpeg'), IMAGETYPE_PNG => array('output' => 'imagepng', 'create' => 'imagecreatefrompng'), IMAGETYPE_XBM => array('output' => 'imagexbm', 'create' => 'imagecreatefromxbm'), IMAGETYPE_WBMP => array('output' => 'imagewbmp', 'create' => 'imagecreatefromxbm'), ); /** * Whether image was resized or not * * #var bool */ protected $_resized = false; public function open($filename) { $this->_fileName = $filename; $this->getMimeType(); $this->_getFileAttributes(); $this->_imageHandler = call_user_func($this->_getCallback('create'), $this->_fileName); } public function save($destination=null, $newName=null) { $fileName = ( !isset($destination) ) ? $this->_fileName : $destination; if( isset($destination) && isset($newName) ) { $fileName = $destination . "/" . $newName; } elseif( isset($destination) && !isset($newName) ) { $info = pathinfo($destination); $fileName = $destination; $destination = $info['dirname']; } elseif( !isset($destination) && isset($newName) ) { $fileName = $this->_fileSrcPath . "/" . $newName; } else { $fileName = $this->_fileSrcPath . $this->_fileSrcName; } $destinationDir = ( isset($destination) ) ? $destination : $this->_fileSrcPath; if( !is_writable($destinationDir) ) { try { $io = new Varien_Io_File(); $io->mkdir($destination); } catch (Exception $e) { throw new Exception("Unable to write file into directory '{$destinationDir}'. Access forbidden."); } } if (!$this->_resized) { // keep alpha transparency $isAlpha = false; $isTrueColor = false; $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha, $isTrueColor); if ($isAlpha) { if ($isTrueColor) { $newImage = imagecreatetruecolor($this->_imageSrcWidth, $this->_imageSrcHeight); } else { $newImage = imagecreate($this->_imageSrcWidth, $this->_imageSrcHeight); } $this->_fillBackgroundColor($newImage); imagecopy( $newImage, $this->_imageHandler, 0, 0, 0, 0, $this->_imageSrcWidth, $this->_imageSrcHeight ); $this->_imageHandler = $newImage; } } $functionParameters = array(); $functionParameters[] = $this->_imageHandler; $functionParameters[] = $fileName; // set quality param for JPG file type if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_JPEG) { $functionParameters[] = $this->quality(); } // set quality param for PNG file type if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_PNG) { $quality = round(($this->quality() / 100) * 10); if ($quality < 1) { $quality = 1; } elseif ($quality > 10) { $quality = 10; } $quality = 10 - $quality; $functionParameters[] = $quality; } //call_user_func_array($this->_getCallback('output'), $functionParameters); $source_file = $this->_fileSrcPath.'/'.$this->_fileSrcName; $image_info = getimagesize($source_file); $im = new Imagick(); $im->readImage($source_file); //check to see if image needs to be resized (eg. thumbnails) if ($image_info[0] != $this->_imageSrcWidth) { $im->thumbnailImage($this->_imageSrcWidth, $this->_imageSrcHeight); } $im->writeImage($fileName); } public function display() { header("Content-type: ".$this->getMimeType()); call_user_func($this->_getCallback('output'), $this->_imageHandler); } /** * Obtain function name, basing on image type and callback type * * #param string $callbackType * #param int $fileType * #return string * #throws Exception */ private function _getCallback($callbackType, $fileType = null, $unsupportedText = 'Unsupported image format.') { if (null === $fileType) { $fileType = $this->_fileType; } if (empty(self::$_callbacks[$fileType])) { throw new Exception($unsupportedText); } if (empty(self::$_callbacks[$fileType][$callbackType])) { throw new Exception('Callback not found.'); } return self::$_callbacks[$fileType][$callbackType]; } private function _fillBackgroundColor(&$imageResourceTo) { // try to keep transparency, if any if ($this->_keepTransparency) { $isAlpha = false; $transparentIndex = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha); try { // fill truecolor png with alpha transparency if ($isAlpha) { if (!imagealphablending($imageResourceTo, false)) { throw new Exception('Failed to set alpha blending for PNG image.'); } $transparentAlphaColor = imagecolorallocatealpha($imageResourceTo, 0, 0, 0, 127); if (false === $transparentAlphaColor) { throw new Exception('Failed to allocate alpha transparency for PNG image.'); } if (!imagefill($imageResourceTo, 0, 0, $transparentAlphaColor)) { throw new Exception('Failed to fill PNG image with alpha transparency.'); } if (!imagesavealpha($imageResourceTo, true)) { throw new Exception('Failed to save alpha transparency into PNG image.'); } return $transparentAlphaColor; } // fill image with indexed non-alpha transparency elseif (false !== $transparentIndex) { $transparentColor = false; if ($transparentIndex >=0 && $transparentIndex <= imagecolorstotal($this->_imageHandler)) { list($r, $g, $b) = array_values(imagecolorsforindex($this->_imageHandler, $transparentIndex)); $transparentColor = imagecolorallocate($imageResourceTo, $r, $g, $b); } if (false === $transparentColor) { throw new Exception('Failed to allocate transparent color for image.'); } if (!imagefill($imageResourceTo, 0, 0, $transparentColor)) { throw new Exception('Failed to fill image with transparency.'); } imagecolortransparent($imageResourceTo, $transparentColor); return $transparentColor; } } catch (Exception $e) { // fallback to default background color } } list($r, $g, $b) = $this->_backgroundColor; $color = imagecolorallocate($imageResourceTo, $r, $g, $b); if (!imagefill($imageResourceTo, 0, 0, $color)) { throw new Exception("Failed to fill image background with color {$r} {$g} {$b}."); } return $color; } /** * Gives true for a PNG with alpha, false otherwise * * #param string $fileName * #return boolean */ public function checkAlpha($fileName) { return ((ord(file_get_contents($fileName, false, null, 25, 1)) & 6) & 4) == 4; } private function _getTransparency($imageResource, $fileType, &$isAlpha = false, &$isTrueColor = false) { $isAlpha = false; $isTrueColor = false; // assume that transparency is supported by gif/png only if ((IMAGETYPE_GIF === $fileType) || (IMAGETYPE_PNG === $fileType)) { // check for specific transparent color $transparentIndex = imagecolortransparent($imageResource); if ($transparentIndex >= 0) { return $transparentIndex; } // assume that truecolor PNG has transparency elseif (IMAGETYPE_PNG === $fileType) { $isAlpha = $this->checkAlpha($this->_fileName); $isTrueColor = true; return $transparentIndex; // -1 } } if (IMAGETYPE_JPEG === $fileType) { $isTrueColor = true; } return false; } /** * Change the image size * * #param int $frameWidth * #param int $frameHeight */ public function resize($frameWidth = null, $frameHeight = null) { if (empty($frameWidth) && empty($frameHeight)) { throw new Exception('Invalid image dimensions.'); } // calculate lacking dimension if (!$this->_keepFrame) { if (null === $frameWidth) { $frameWidth = round($frameHeight * ($this->_imageSrcWidth / $this->_imageSrcHeight)); } elseif (null === $frameHeight) { $frameHeight = round($frameWidth * ($this->_imageSrcHeight / $this->_imageSrcWidth)); } } else { if (null === $frameWidth) { $frameWidth = $frameHeight; } elseif (null === $frameHeight) { $frameHeight = $frameWidth; } } // define coordinates of image inside new frame $srcX = 0; $srcY = 0; $dstX = 0; $dstY = 0; $dstWidth = $frameWidth; $dstHeight = $frameHeight; if ($this->_keepAspectRatio) { // do not make picture bigger, than it is, if required if ($this->_constrainOnly) { if (($frameWidth >= $this->_imageSrcWidth) && ($frameHeight >= $this->_imageSrcHeight)) { $dstWidth = $this->_imageSrcWidth; $dstHeight = $this->_imageSrcHeight; } } // keep aspect ratio if ($this->_imageSrcWidth / $this->_imageSrcHeight >= $frameWidth / $frameHeight) { $dstHeight = round(($dstWidth / $this->_imageSrcWidth) * $this->_imageSrcHeight); } else { $dstWidth = round(($dstHeight / $this->_imageSrcHeight) * $this->_imageSrcWidth); } } // define position in center (TODO: add positions option) $dstY = round(($frameHeight - $dstHeight) / 2); $dstX = round(($frameWidth - $dstWidth) / 2); // get rid of frame (fallback to zero position coordinates) if (!$this->_keepFrame) { $frameWidth = $dstWidth; $frameHeight = $dstHeight; $dstY = 0; $dstX = 0; } // create new image $isAlpha = false; $isTrueColor = false; $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha, $isTrueColor); if ($isTrueColor) { $newImage = imagecreatetruecolor($frameWidth, $frameHeight); } else { $newImage = imagecreate($frameWidth, $frameHeight); } // fill new image with required color $this->_fillBackgroundColor($newImage); // resample source image and copy it into new frame imagecopyresampled( $newImage, $this->_imageHandler, $dstX, $dstY, $srcX, $srcY, $dstWidth, $dstHeight, $this->_imageSrcWidth, $this->_imageSrcHeight ); $this->_imageHandler = $newImage; $this->refreshImageDimensions(); $this->_resized = true; } public function rotate($angle) { /* $isAlpha = false; $backgroundColor = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha); list($r, $g, $b) = $this->_backgroundColor; if ($isAlpha) { $backgroundColor = imagecolorallocatealpha($this->_imageHandler, 0, 0, 0, 127); } elseif (false === $backgroundColor) { $backgroundColor = imagecolorallocate($this->_imageHandler, $r, $g, $b); } $this->_imageHandler = imagerotate($this->_imageHandler, $angle, $backgroundColor); //*/ $this->_imageHandler = imagerotate($this->_imageHandler, $angle, $this->imageBackgroundColor); $this->refreshImageDimensions(); } public function watermark($watermarkImage, $positionX=0, $positionY=0, $watermarkImageOpacity=30, $repeat=false) { list($watermarkSrcWidth, $watermarkSrcHeight, $watermarkFileType, ) = getimagesize($watermarkImage); $this->_getFileAttributes(); $watermark = call_user_func($this->_getCallback( 'create', $watermarkFileType, 'Unsupported watermark image format.' ), $watermarkImage); $merged = false; if ($this->getWatermarkWidth() && $this->getWatermarkHeigth() && ($this->getWatermarkPosition() != self::POSITION_STRETCH) ) { $newWatermark = imagecreatetruecolor($this->getWatermarkWidth(), $this->getWatermarkHeigth()); imagealphablending($newWatermark, false); $col = imagecolorallocate($newWatermark, 255, 255, 255); imagecolortransparent($newWatermark, $col); imagefilledrectangle($newWatermark, 0, 0, $this->getWatermarkWidth(), $this->getWatermarkHeigth(), $col); imagealphablending($newWatermark, true); imageSaveAlpha($newWatermark, true); imagecopyresampled( $newWatermark, $watermark, 0, 0, 0, 0, $this->getWatermarkWidth(), $this->getWatermarkHeigth(), imagesx($watermark), imagesy($watermark) ); $watermark = $newWatermark; } if( $this->getWatermarkPosition() == self::POSITION_TILE ) { $repeat = true; } elseif( $this->getWatermarkPosition() == self::POSITION_STRETCH ) { $newWatermark = imagecreatetruecolor($this->_imageSrcWidth, $this->_imageSrcHeight); imagealphablending($newWatermark, false); $col = imagecolorallocate($newWatermark, 255, 255, 255); imagecolortransparent($newWatermark, $col); imagefilledrectangle($newWatermark, 0, 0, $this->_imageSrcWidth, $this->_imageSrcHeight, $col); imagealphablending($newWatermark, true); imageSaveAlpha($newWatermark, true); imagecopyresampled( $newWatermark, $watermark, 0, 0, 0, 0, $this->_imageSrcWidth, $this->_imageSrcHeight, imagesx($watermark), imagesy($watermark) ); $watermark = $newWatermark; } elseif( $this->getWatermarkPosition() == self::POSITION_CENTER ) { $positionX = ($this->_imageSrcWidth/2 - imagesx($watermark)/2); $positionY = ($this->_imageSrcHeight/2 - imagesy($watermark)/2); imagecopymerge( $this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); } elseif( $this->getWatermarkPosition() == self::POSITION_TOP_RIGHT ) { $positionX = ($this->_imageSrcWidth - imagesx($watermark)); imagecopymerge( $this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); } elseif( $this->getWatermarkPosition() == self::POSITION_TOP_LEFT ) { imagecopymerge( $this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); } elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_RIGHT ) { $positionX = ($this->_imageSrcWidth - imagesx($watermark)); $positionY = ($this->_imageSrcHeight - imagesy($watermark)); imagecopymerge( $this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); } elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_LEFT ) { $positionY = ($this->_imageSrcHeight - imagesy($watermark)); imagecopymerge( $this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); } if( $repeat === false && $merged === false ) { imagecopymerge( $this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); } else { $offsetX = $positionX; $offsetY = $positionY; while( $offsetY <= ($this->_imageSrcHeight+imagesy($watermark)) ) { while( $offsetX <= ($this->_imageSrcWidth+imagesx($watermark)) ) { imagecopymerge( $this->_imageHandler, $watermark, $offsetX, $offsetY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity() ); $offsetX += imagesx($watermark); } $offsetX = $positionX; $offsetY += imagesy($watermark); } } imagedestroy($watermark); $this->refreshImageDimensions(); } public function crop($top=0, $left=0, $right=0, $bottom=0) { if( $left == 0 && $top == 0 && $right == 0 && $bottom == 0 ) { return; } $newWidth = $this->_imageSrcWidth - $left - $right; $newHeight = $this->_imageSrcHeight - $top - $bottom; $canvas = imagecreatetruecolor($newWidth, $newHeight); if ($this->_fileType == IMAGETYPE_PNG) { $this->_saveAlpha($canvas); } imagecopyresampled( $canvas, $this->_imageHandler, 0, 0, $left, $top, $newWidth, $newHeight, $newWidth, $newHeight ); $this->_imageHandler = $canvas; $this->refreshImageDimensions(); } public function checkDependencies() { foreach( $this->_requiredExtensions as $value ) { if( !extension_loaded($value) ) { throw new Exception("Required PHP extension '{$value}' was not loaded."); } } } private function refreshImageDimensions() { $this->_imageSrcWidth = imagesx($this->_imageHandler); $this->_imageSrcHeight = imagesy($this->_imageHandler); } function __destruct() { #imagedestroy($this->_imageHandler); } /* * Fixes saving PNG alpha channel */ private function _saveAlpha($imageHandler) { $background = imagecolorallocate($imageHandler, 0, 0, 0); ImageColorTransparent($imageHandler, $background); imagealphablending($imageHandler, false); imagesavealpha($imageHandler, true); } }
Have you tried the hackathon magento imagemagick enabler? [https://github.com/magento-hackathon/Perfect_Watermarks][1] I am going to test this in a minute, so this suggestion is absolutly untested at the moment.
Fast resize picture tool/script
I have a lot of images (500,000 +) in a folder on the server organized by date. I made a PHP script to copy and crop each JPG file on a subfolder (thumb), but it's very slow since PHP doesn't support multithreading. I want advice on how to proceed. Is Python a good option for this? Is there a good tool, or how can I improve my resize function? You can also take a look to my PHP Code
You can do it in PHP without any problem, simulating threads instead of using them directly. Actually, PHP doesn't have native threads (you can eventuallĀ„ use libraries but that's not very useful in your case). In your code, instead of calling : static::Crop($file,$destination,$tn_w = 300,$tn_h =200,$quality = 100,$wmsource = false); Why not doing : $array = array($file, $destination, $tn_w = 300, $tn_h = 200, $quality = 100, $wmsource = 0); $command = "/usr/bin/php crop.php"; foreach ($array as $arg) { $command .= ' ' . escapeshellarg($arg); } exec("$command &"); // note the & which release your execution usleep(100000); And you put your cropping function inside crop.php, and then call it like : list($exec, $file, $destination, $tn_w, $tn_h, $quality, $wmsource) = $argv; static::Crop($file,$destination,$tn_w = 300,$tn_h =200,$quality = 100,$wmsource = false); This will do the job. You can also simulate mutexes using a file if you want to avoid usleep and control how many crops are running at once, that's really up to you. You definitely can do such work in PHP.
But php cgi support multithreading. Why not using exec()? Or you can use a shell script and for the conversion php cgi?
by Use This class <?php class thumbnail_images { // get var $PathImgOld; var $PathImgNew; var $NewWidth; var $NewHeight; // tmp var $mime; function imagejpeg_new ($NewImg,$path_img) { if ($this->mime == 'image/jpeg' or $this->mime == 'image/pjpeg') imagejpeg($NewImg,$path_img); elseif ($this->mime == 'image/gif') imagegif($NewImg, $path_img); elseif ($this->mime == 'image/png') imagepng($NewImg, $path_img); else return(false); return(true); } function imagecreatefromjpeg_new($path_img) { if ($this->mime == 'image/jpeg' or $this->mime == 'image/pjpeg') $OldImg = imagecreatefromjpeg($path_img); elseif ($this->mime == 'image/gif') $OldImg = imagecreatefromgif($path_img); elseif ($this->mime == 'image/png') $OldImg = imagecreatefrompng($path_img); else return(false); return($OldImg); } function create_thumbnail_images() { $PathImgOld = $this->PathImgOld; $PathImgNew = $this->PathImgNew; $NewWidth = $this->NewWidth; $NewHeight = $this->NewHeight; $Oldsize = #getimagesize($PathImgOld); $this->mime = $Oldsize['mime']; $OldWidth = $Oldsize[0]; $OldHeight = $Oldsize[1]; if ($NewHeight == '' and $NewWidth != '') { $NewHeight = ceil(($OldHeight * $NewWidth) / $OldWidth); } elseif ($NewWidth == '' and $NewHeight != '') { $NewWidth = ceil(($OldWidth * $NewHeight) / $OldHeight); } elseif ($NewHeight == '' and $NewWidth == '') { return(false); } $OldHeight_castr = ceil(($OldWidth * $NewHeight) / $NewWidth); $castr_bottom = ($OldHeight - $OldHeight_castr) / 2; $OldWidth_castr = ceil(($OldHeight * $NewWidth) / $NewHeight); $castr_right = ($OldWidth - $OldWidth_castr) / 2; if ($castr_bottom>0) { $OldWidth_castr = $OldWidth; $castr_right = 0; } elseif ($castr_right>0) { $OldHeight_castr = $OldHeight; $castr_bottom = 0; } else { $OldWidth_castr = $OldWidth; $OldHeight_castr = $OldHeight; $castr_right = 0; $castr_bottom = 0; } $OldImg = $this->imagecreatefromjpeg_new($PathImgOld); if ($OldImg) { $NewImg_castr = imagecreatetruecolor($OldWidth_castr, $OldHeight_castr); if ($NewImg_castr) { imagecopyresampled($NewImg_castr, $OldImg, 0, 0, $castr_right, $castr_bottom, $OldWidth_castr, $OldHeight_castr, $OldWidth_castr, $OldHeight_castr); $NewImg = imagecreatetruecolor($NewWidth, $NewHeight); if ($NewImg) { imagecopyresampled($NewImg, $NewImg_castr, 0, 0, 0, 0, $NewWidth, $NewHeight, $OldWidth_castr, $OldHeight_castr); imagedestroy($NewImg_castr); imagedestroy($OldImg); if (!$this->imagejpeg_new($NewImg, $PathImgNew)) return (false); imagedestroy($NewImg); } } } else { return(false); } return(true); } } ?> Now use it $width = $_REQUEST['img_width']; $height = $_REQUEST['img_height']; // example $obj_img = new thumbnail_images(); $obj_img->PathImgOld = 'Old_image.jpg'; // Image for resize $obj_img->PathImgNew = 'my_image_new_formSubURLkki.jpg'; // New Image Path $obj_img->NewWidth = $width; $obj_img->NewHeight = $height; if (!$obj_img->create_thumbnail_images()) echo "error"; else { echo 'Image Maked andsave in directory'; }
PHP: Resize/making thumbnails?
Helo i now have finish making my upload profilephoto system. Now i want include creating thumbnails of the uploaded image in different sizes eg 48x48 and 148x50, how can i do this? Example / good tutorials for this?
You will need to use PHP's GD library or ImageMagick library. First find out which, if any, you have installed on your development and production environments. Then start looking for tutorials depending on which one you want to use. There are many out there. GD usually comes pre-packed with PHP5.
Back then I used imagemagick. $ convert -resize 48x48 xyz.jpg xyz_48x48.jpg It is also available as a php module: http://php.net/manual/en/book.imagick.php But I haven't used that one, but I suppose it knows exactly the same as the command line variant.
Tutorial with imagecreatefrom()... , imagecopyresized(), imagejpeg()
Here my class for resizing. Replace the 150 occurences with a variable. <?php /** * Takes an image and creates a thumbnail of it. */ class ImageThumbnail { private $thumbnail; /** * Create a new object * * #param string $source Location of the original image (can be null if set using create()) * #param string $extension File extension, if it has been obfuscated (e.g. moved to PHP's tmp dir) */ public function __construct($source, $extension) { if ($source) { $this->create($source, $extension); } } public function create($source, $extension = null) { if (!$extension) { $parts = explode('.', $source); // get the file extension $extension = array_pop($parts); } else { $extension = ltrim($extension, '.'); // get rid of any prefixing dots } // Get the images size $size = getImageSize($source); // Width > height if ($size[0] > $size[1]) { $width = 150; $height = (int) (150 * $size[1] / $size[0]); } // Height > width else { $width = (int) (150 * $size[0] / $size[1]); $height = 150; } $readFunc = 'imageCreateFrom'.filenameToImageMime($source); if (!$source = $readFunc($source)) { throw new Exception('The source image is unreadable'); } // Create an blank image for the thumbnail $thumbnail = imageCreateTrueColor($width, $height); // Copy source image onto new image imageCopyResized($thumbnail, $source, 0, 0, 0, 0, $width, $height, $size[0], $size[1]); $this->thumbnail = $thumbnail; } public function getThumbnail() { return $this->thumbnail; } public function move($target) { $func = 'image'.filenameToImageMime($target); $func($this->thumbnail, $target); imageDestroy($this->thumbnail); } }
function makenicepic($srcfile,$tofile,$maxwidth,$maxheight) { //global $_SGLOBAL; // check file exist if (!file_exists($srcfile)) { return ''; } $dstfile = $tofile; include_once(S_ROOT.'./data/data_setting.php'); // //size $tow = $maxwidth; $toh =$maxheight; $make_max = 0; $maxtow = 950; $maxtoh = 700; $make_max = 1; $im = ''; if($data = getimagesize($srcfile)) { if($data[2] == 1) { $make_max = 0;//gif skip if(function_exists("imagecreatefromgif")) { $im = imagecreatefromgif($srcfile); } } elseif($data[2] == 2) { if(function_exists("imagecreatefromjpeg")) { $im = imagecreatefromjpeg($srcfile); } } elseif($data[2] == 3) { if(function_exists("imagecreatefrompng")) { $im = imagecreatefrompng($srcfile); } } } if(!$im) return ''; $srcw = imagesx($im); $srch = imagesy($im); $towh = $tow/$toh; $srcwh = $srcw/$srch; if($towh <= $srcwh){ $ftow = $tow; $ftoh = $ftow*($srch/$srcw); $fmaxtow = $maxtow; $fmaxtoh = $fmaxtow*($srch/$srcw); } else { $ftoh = $toh; $ftow = $ftoh*($srcw/$srch); $fmaxtoh = $maxtoh; $fmaxtow = $fmaxtoh*($srcw/$srch); } if($srcw <= $maxtow && $srch <= $maxtoh) { $make_max = 0; } if($srcw > $tow || $srch > $toh) { if(function_exists("imagecreatetruecolor") && function_exists("imagecopyresampled") && #$ni = imagecreatetruecolor($ftow, $ftoh)) { imagecopyresampled($ni, $im, 0, 0, 0, 0, $ftow, $ftoh, $srcw, $srch); if($make_max && #$maxni = imagecreatetruecolor($fmaxtow, $fmaxtoh)) { imagecopyresampled($maxni, $im, 0, 0, 0, 0, $fmaxtow, $fmaxtoh, $srcw, $srch); } } elseif(function_exists("imagecreate") && function_exists("imagecopyresized") && #$ni = imagecreate($ftow, $ftoh)) { imagecopyresized($ni, $im, 0, 0, 0, 0, $ftow, $ftoh, $srcw, $srch); if($make_max && #$maxni = imagecreate($fmaxtow, $fmaxtoh)) { imagecopyresized($maxni, $im, 0, 0, 0, 0, $fmaxtow, $fmaxtoh, $srcw, $srch); } } else { return ''; } if(function_exists('imagejpeg')) { imagejpeg($ni, $dstfile); //big pic if($make_max) { imagejpeg($maxni, $srcfile); } } elseif(function_exists('imagepng')) { imagepng($ni, $dstfile); if($make_max) { imagepng($maxni, $srcfile); } } imagedestroy($ni); if($make_max) { imagedestroy($maxni); } } imagedestroy($im); if(!file_exists($dstfile)) { return ''; } else { return $dstfile; } }