<?php
// ------------------------------------------------------------------------ //
// RImageManipulator.class.php,v 1.0 2007/02/15 19:00:00 R.Brambilla //
// ------------------------------------------------------------------------ //
// RImageManipulator - Image Manipulation Class //
// Copyright (C) 2007 Riccardo Brambilla //
// <ribrambilla@tiscali.it> //
// ------------------------------------------------------------------------ //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// You may not change or alter any portion of this comment or credits //
// of supporting developers from this source code or any supporting //
// source code which is considered copyrighted (c) material of the //
// original comment or credit authors. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program; if not, write to the Free Software //
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //
// ------------------------------------------------------------------------ //
/**
* Options are detected from a simple config. file
* HINT => Change path of the ini file in "parse_ini_file" function to an absolute one
* dirname(__FILE__) works well only if conf.ini.php file is saved
* in the same folder as the class file's one
*/
$conf = parse_ini_file( dirname(__FILE__) . "/conf.ini.php");
$lang = $conf['lang'];
$er_image_w = $conf['er_image_w'];
$er_image_h = $conf['er_image_h'];
$debug_mode = $conf['debug_mode'];
/**
* Including files
* [1] Language file
* HINT => Change path of the lang file to an absolute one
* dirname(__FILE__) works well only if lang file is saved
* in the same folder as the class file's one
*/
if(file_exists( dirname(__FILE__) . "/" . $lang . ".php" )){
include_once( dirname(__FILE__) . "/" . $lang . ".php" );
}
else {
die("LANGUAGE FILE NOT FOUND!");
}
/**
* Handles images
* Operations supported: resize ANDOR rotate ANDOR apply filters ANDOR interlace AND save the brand new Image
*
* @author Riccardo Brambilla aka ricketno <riccardobra@gmail.com>
* @package RImageManipulator
* @version 1.0 Feb 2007 PHP5
*
*/
class RImageManipulator
{
/**
* Class var :: $image_pathname
*
* @var string
* @access private
*/
private $image_pathname;
/**
* Class var :: $image_name
*
* @var string
* @access private
*/
private $image_name;
/**
* Class var :: $image_path
*
* @var string
* @access private
*/
private $image_path;
/**
* Class var :: $ext
*
* @var string
* @access private
*/
private $ext;
/**
* Class var :: $new_w
*
* @var int
* @access private
*/
private $new_w;
/**
* Class var :: $new_h
*
* @var int
* @access private
*/
private $new_h;
/**
* Class var :: $new_name
*
* @var string
* @access private
*/
private $new_name;
/**
* Class var :: $mantain_prop
*
* @var bool
* @access private
*/
private $constrain_prop = true;
/**
* Class var :: $allowed_ext
*
* @var array
* @access private
*/
private $allowed_ext = array( 'jpg', 'jpeg', 'png', 'gif' );
/**
* Class var :: image resource
*
* @var resource
* @access private
*/
private $im_resource;
/**
* Class var :: $img_info
*
* @var array
* @access private
*/
private $im_resource_info = array();
/**
* Class var :: $error_string
* Holds infos about errors occurred
*
* @var string
* @access public
*/
public $error_string = "";
/**
* Class var :: $memory_needed
* Memory needed for script to perform actions
*
* @var int
* @access private
*/
private $memory_needed = 0;
/**
* CLASS Constants
* Defaul Size values
* Note: _WIDTH & _HEIGHT are both of type int
*
*/
const _WIDTH = 120;
const _HEIGHT = 120;
/**
* CLASS Constants
* Constants used by the alloc(), predictMemoryUsage() functions
*
*/
const _MB = 1048576; // Bytes in a MB
const _64K = 65536; // Bytes in 64K
const _TFACTOR = 4.8; // This value works for me :: you can change it
const _UPPERLIMIT = 83886080; // 80MB ( in Bytes ) Limit :: you can change it
/**
* Class Constructor
*
* @param string $image_pathname
* @param string $new_name
* @return RImageManipulator
*
* @access public
*/
public function __construct( $image_pathname, $new_name = "" )
{
// :: CHECKING INPUTS
if(!is_string($image_pathname) || !ereg(".", $image_pathname))
{
$this->setError(_ERR_PATHINVALID, 1);
}
if(!is_file($image_pathname) || !file_exists($image_pathname))
{
$this->setError(_ERR_NOTAFILE, 1);
}
// :: SETTING CLASS VARS
// : Extension manipulation
$this->image_pathname = $image_pathname;
$path_components = explode("/", $this->image_pathname);
$image_name_ext = array_pop($path_components);// returns the last element of the path array ( name.ext )
// : If image is in the same directory of the script then path is dirname(__FILE__)
// : else path is the result of the implode function
$this->image_path = sizeof($path_components > 0) ? implode("/", $path_components) : dirname(__FILE__);
// : Detecting image name and extension
$name_components = explode(".", $image_name_ext);
$this->ext = strtolower(array_pop($name_components));// extracts last component
$this->image_name = implode(".", $name_components);
// : Checking if extension is allowed
if( empty($this->ext) )
$this->setError(_ERRNOTALLOWED, 1);
if( !in_array($this->ext, $this->allowed_ext) )
$this->setError(_ERRNOTALLOWED, 1);
// : New name if any ; else original name is used
$this->new_name = empty($new_name) ? $this->image_name : $new_name;
// : Creates the image resource to work on
$this->createImageResource();
}// ef
/**
* Get class var value using class var name
*
* @param string $var_name
* @return mixed
*
* @example $extension = $object->getVar('ext');
* @access public
*/
public function getVar($var_name = "")
{
return (isset($this->$var_name) && !empty($var_name)) ? $this->$var_name : "";
}// ef
/**
* Creates an image resource from filesystem
* Appropriate function is chose on the base of file's extension
*
* @access private
*/
private function createImageResource()
{
// : Get current image size, extra infos like channels and bits
$this->im_resource_info = getimagesize($this->image_pathname);
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: Creating an empty image
switch($this->ext)
{
default:
case "jpg":// JPG Images
case "jpeg":
if(!($img = imagecreatefromjpeg($this->image_pathname)))
{
// : Setting the error string
$this->setError(_ERR_IMAGECREATION);
$this->showImgError();
}
break;
case "png":// PNG Images :: Note: Right pronunciation is "ping" NOT "pee en gee" :)
if(!($img = @imagecreatefrompng($this->image_pathname)))
{
// : Setting the error string
$this->setError(_ERR_IMAGECREATION);
$this->showImgError();
}
break;
case "gif":// GIF Images :: Note: Right pronunciation is "jif" NOT "GIF" :)
// Note: GIF Support is expected to return in a GD library version released after mid 2004
if( function_exists('imagecreatefromgif') && function_exists('imagegif'))
{
if((!$img = @imagecreatefromgif($this->image_pathname)))
{
// : Setting the error string
$this->setError(_ERR_IMAGECREATION);
$this->showImgError();
}
}
else
{
// Gif Support disabled
$this->setError(_ERR_GIFNOTSUPPORTED);
$this->showImgError();
}
break;
}// ends switch
// : Image created is saved as a class var
// : Type is 'resource'
$this->im_resource = $img;
}// ef
/**
* Resizes the image, constrains proportions if asked
*
* @param int $new_w
* @param int $new_h
* @param bool $mantain_prop
*
* @access private
*/
public function resize( $new_w = 0, $new_h = 0, $constrain_prop = true)
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: CHECKING INPUTS
if(!is_int($new_w) || empty($new_w))
{
$new_w = self::_WIDTH;
}
if(!is_int($new_h) || empty($new_h))
{
$new_h = self::_HEIGHT;
}
if(!is_bool($constrain_prop))
{
$constrain_prop = true;
}
// Check if resource is valid
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
// : New Size
$this->new_w = $new_w;
$this->new_h = $new_h;
// : Proportion must or must not be kept
$this->constrain_prop = $constrain_prop;
// Image Size
$img_width = $this->im_resource_info[0];// W
$img_height = $this->im_resource_info[1];// H
// :: CONSTRAIN PROPORTION
if( $this->constrain_prop )
{
// Ratio
$size_prop = round( ($img_width/$img_height), 3 );
// W = H square
if( $size_prop == 1 )
{
if( $img_width === $this->new_w && $img_height === $this->new_h)
{
$tmp_img = $this->im_resource;// no changes needed
}
else
{
// New W-H
$new_width = $this->new_w;
$new_height = $this->new_h;
// Copy ( resample )
$tmp_img = ImageCreateTrueColor( $new_width, $new_height );
imagecopyresampled( $tmp_img, $this->im_resource, 0, 0, 0, 0,$this->new_w, $this->new_h, $img_width, $img_height );
}
}// ends square case
elseif( $size_prop > 1 )// W > H
{
// : Ratio must be computed
if( $img_width > $this->new_w )
{
$ratio = ( $img_width/$this->new_w );
$new_height = floor( $img_height/$ratio );
}
else
{
$ratio = ( $this->new_w/$img_width );
$new_height = floor( $img_height*$ratio );
}
$new_width = $this->new_w;
// Copy ( resample )
$tmp_img = ImageCreateTrueColor($new_width,$new_height);
imagecopyresampled($tmp_img, $this->im_resource, 0, 0, 0, 0,$new_width,$new_height, $img_width, $img_height);
}// ends W > H
elseif( $size_prop < 1 )// W < H
{
// : Ratio must be computed
if( $img_height > $this->new_h )
{
$ratio = ( $img_height/$this->new_h );
$new_width = floor( $img_width/$ratio );
}
else
{
$ratio = ( $this->new_h/$img_height );
$new_width = floor( $img_width*$ratio );
}
$new_height = $this->new_h;
// Copy ( resample )
$tmp_img = ImageCreateTrueColor($new_width,$new_height);
imagecopyresampled( $tmp_img, $this->im_resource, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height);
}// ends W < H
else
{
$this->setError(_ERR_RESIZE);// Error
}
// "Refreshing" resource
$this->im_resource = $tmp_img;
}// ends if costrain proportions
else // Note: PROPORTIONS WILL BE LOST
{
// Copy ( resample ) width are height are taken directly from user input
$tmp_img = ImageCreateTrueColor($this->new_w, $this->new_h);
imagecopyresampled( $tmp_img, $this->im_resource, 0, 0, 0, 0, $this->new_w, $this->new_h, $img_width, $img_height);
// "Refreshing" resource
$this->im_resource = $tmp_img;
}// ends main else
$this->im_resource = $tmp_img;
// :: Size infos must be refreshed
// :: Now size infos are taken directly from the resource itself
$this->im_resource_info[0] = imagesx($this->im_resource);
$this->im_resource_info[1] = imagesy($this->im_resource);
}// ef
/**
* Rotates image by $angle degrees
* IMPORTANT NOTE: imagerotate function does not preserve infos about transparency
*
* @param int $angle 0 < angle < 360
* @param int $bgc "background" color :: specifies the color of the uncovered zone after the rotation.
* @param bool $clockwise rotation is clockwise ( default ) or counter clockwise
*
* @access public
*/
public function rotate($angle, $bgc = 0, $clockwise = true)
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: CHECKING INPUTS
if(!is_int($angle) || ($angle % 90) != 0)
{
$angle = 90;// angle must be a multiple of 90
}
if(!is_int($bgc) || $bgc > 360 || $bgc < 0 )
{
$bgc = 0;
}
if( $clockwise == true )
{
$angle = abs(360 - $angle);
}
// Check if resource is valid
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
// : Rotation
$this->im_resource = @imagerotate($this->im_resource, $angle, $bgc ) or $this->setError(_ERR_ROTATION);
}// ef
/**
* Applies filters provided by imagefilter function
* Filter Constants are numeric; range is between 0 and 10
* Performs checks on optional args number
* Filter names are:
*
* IMG_FILTER_NEGATE => 0
* IMG_FILTER_GRAYSCALE => 1
* IMG_FILTER_BRIGHTNESS => 2
* IMG_FILTER_CONTRAST => 3
* IMG_FILTER_COLORIZE => 4
* IMG_FILTER_EDGEDETECT => 5
* IMG_FILTER_EMBOSS => 6
* IMG_FILTER_GAUSSIAN_BLUR => 7
* IMG_FILTER_SELECTIVE_BLUR => 8
* IMG_FILTER_MEAN_REMOVAL => 9
* IMG_FILTER_SMOOTH => 10
*
* @param int $filter_index
* @param array $args optional args
*
* @access public
*/
public function applyFilter( $filter_index = 0 )
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: CHECK
// Index is not in the range 0 - 10
if($filter_index < 0 || $filter_index > 10)
{
$this->setError(_ERR_FILTERDOESNOTEXIST);
}
// Check if resource is valid
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
// : How many args were sent to the function
$args_num = func_num_args();
// : Args
$args = func_get_args();
// :: Switch between indexes, options have their own number of parameters
switch($filter_index)
{
default:
case IMG_FILTER_NEGATE:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_GRAYSCALE:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_BRIGHTNESS:
if($args_num != 2)
$this->setError(_ERR_FILTERPARAMNUMBER);
@imagefilter($this->im_resource, $filter_index, $args[1]);
break;
case IMG_FILTER_CONTRAST:
if($args_num != 2)
$this->setError(_ERR_FILTERPARAMNUMBER);
@imagefilter($this->im_resource, $filter_index, $args[1]);
break;
case IMG_FILTER_COLORIZE:
if($args_num != 4)
$this->setError(_ERR_FILTERPARAMNUMBER);
@imagefilter($this->im_resource, $filter_index, $args[1], $args[2], $args[3]);
break;
case IMG_FILTER_EDGEDETECT:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_EMBOSS:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_GAUSSIAN_BLUR:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_SELECTIVE_BLUR:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_MEAN_REMOVAL:
@imagefilter($this->im_resource, $filter_index);
break;
case IMG_FILTER_SMOOTH:
if($args_num != 2)
$this->setError(_ERR_FILTERPARAMNUMBER);
@imagefilter($this->im_resource, $filter_index, $args[1]);
break;
}// ends switch
}// ef
/**
* Interlace or deinterlace image
*
* @param int $interlace_bit_val
*/
public function interlace( $interlace_bit_val = 0 )
{
// :: CHECKING INPUTS
if( !in_array($interlace_bit_val, array(1, 0)) )
$interlace_bit_val = 0;
// : We may have to dinamically allocate some extra memory
$this->alloc();
// Check if resource is valid
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
// : Interlace op
@imageinterlace($this->im_resource, $interlace_bit_val);
}// ef
/**
* Crops image
*
* @param int $crop_width
* @param int $crop_height
* @param int $d_x
* @param int $d_y
* @param int $src_x
* @param int $src_y
* @param array $bgc
*
* @access public
*/
public function crop($crop_width, $crop_height, $d_x = 0, $d_y = 0, $src_x = 0, $src_y = 0, $bgc = array())
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: CHECKING INPUTS
// Is resource a valid one
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
if(!is_int($crop_width))
{
$crop_width = $this->im_resource_info[0];
}
if(!is_int($crop_height))
{
$crop_height = $this->im_resource_info[1];
}
if(!is_array($bgc) || count($bgc) !== 3)
{
$bgc = array(255, 255, 255);
}
// : Fill
$tmp_img = ImageCreateTrueColor($crop_width, $crop_height);
$bg_color = imagecolorallocate($tmp_img, $bgc[0], $bgc[1], $bgc[2]);
imagefill($tmp_img, 0, 0, $bg_color);
// Copy ( resample )
@imagecopyresampled( $tmp_img, $this->im_resource, (int)$d_x, (int)$d_y, (int)$src_x, (int)$src_y, $crop_width, $crop_height, $crop_width, $crop_height);
// :: Size infos must be refreshed
$this->im_resource_info[0] = $crop_width;
$this->im_resource_info[1] = $crop_height;
$this->im_resource = $tmp_img;
}// ef
/**
* Draw a message on the image
*
* @param string $msg
* @param int $font
* @param int $x
* @param int $y
* @param array $text_color
*
* @access public
*/
public function drawString($msg, $font = 2, $x = 0, $y = 0, $text_color = array())
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: CHECKING INPUTS
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
if(!is_string($msg))
{
$this->setError(_ERR_DRAWNOMSG);
}
if(!is_int($x) || !is_int($y))
{
$x = $y = 0;
}
if($font < 1 || $font > 5)
{
$font = 2;
}
if(!is_array($text_color) || count($text_color) !== 3)
{
$text_color = array(255, 255, 255);
}
$text_color = imagecolorallocate($this->im_resource, $text_color[0], $text_color[1], $text_color[2]);// a kind of white
// : Writing a message on the canvas
@imagestring($this->im_resource, $font, $x, $y, $msg, $text_color) or $this->setError(_ERR_DS);
}// ef
/**
* Generate a fog-like effect
* It draws an alpha indexed gray rectangle on the image
* Note: alpha is 0 to 127, where 0 is opaque
*
* @param int $alpha
*
* @access public
*/
function fog($alpha = 63)
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
if(!is_numeric($alpha) || $alpha < 0 || $alpha >127)
{
$alpha = 63;
}
// :: $fog is a light gray, put on the image generate a fog-like effect
$fog = imagecolorallocatealpha($this->im_resource, 211, 211, 211, (int)$alpha);
@imagefilledrectangle($this->im_resource, 0, 0, $this->im_resource_info[0], $this->im_resource_info[1], $fog) or $this->setError(_ERR_FOG);
}// ef
/**
* Draw a string ( TRUE TYPE FONTS ) on image with a given angle
*
* @param int $size font size
* @param int $angle angolo
* @param int $x
* @param int $y
* @param array $text_color
* @param string $font
* @param string $msg
*
* @access public
*/
public function drawTText($size, $angle, $x, $y, $text_color = array(), $msg, $font = 'arial.ttf')
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
// :: CHECKING INPUTS
if (!is_resource($this->im_resource))
{
$this->setError(_ERR_NOTAVALIDRESOURCE, 1);
}
if(!is_numeric($size))
{
$size = 10;
}
if(!is_numeric($angle))
{
$angle = 0;
}
if(!is_int($x) || !is_int($y))
{
$x = $y = 0;
}
if(!is_string($font))
{
$font = 'arial.ttf';
}
if(!is_array($text_color) || count($text_color) !== 3)
{
$text_color = array(255, 255, 255);
}
if(!is_string($msg))
{
$this->setError(_ERR_DRAWNOMSG);
}
// : Allocating text color
$text_color = imagecolorallocate($this->im_resource, $text_color[0], $text_color[1], $text_color[2]);// a kind of white
// : Draw string
@imagettftext($this->im_resource, $size, $angle, $x, $y, $text_color, $font, $msg) or $this->setError(_ERR_TTEXT);
}// ef
/**
* Gives a sepia-like effect
* [1] Image is converted in grayscale
* [2] Image is converted from RGB to CMYK
* [3] CMYK values are changed to obtain a sepia-like effect
* [4] CMKY values are converted to RGB
*
* @access public
*/
public function sepia()
{
$this->alloc();
// : First we need to grayscale the image
$this->applyFilter(1);
// : Let's create an empty image
$im = imagecreatetruecolor($this->im_resource_info[0], $this->im_resource_info[1]);
// :: Looping image's pixels
for ($y = 0; $y < $this->im_resource_info[1]; $y++)
{
for ($x = 0; $x < $this->im_resource_info[0]; $x++)
{
/**
* THESE LINES FROM PHP MANUAL
* FUNCTION: imagecolorat
* Returns the index of the color of the pixel at the specified location
* Use bitshifting and masking to access the distinct red, green and blue component values
*/
$rgb = imagecolorat($this->im_resource, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
// : We need CMYK values to obtain our sepia-like effect
list($C, $M, $Y, $K) = $this->rgbToCMYK($r, $g, $b);
// : These are custom values, they works for me
// : You can increase $M ( magenta channel ) to obtain
// : a more "purpled" sepia effect
$M = $M + 0.14;
$Y = $Y + 0.30;
// : Reconvert to RGB
list($r, $g, $b) = $this->cmykToRGB($C, $M, $Y, $K);
// : This is our new sepia-like color
$col = imagecolorallocate($im, $r, $g, $b);
// : Setting pixel RGB Value
imagesetpixel($im, $x, $y, $col);
}// end inner for
}// ends 2D loop
$this->im_resource = $im;
}// ef
/**
* Converts RGB values to CMYK values
* Function first converts to CMY and then
* performs the convertion between CMY and CMYK
*
* Algorithm found at easyrgb http://www.easyrgb.com/ ( pseudocode )
* Here's my php implementation
*
* @param int $r
* @param int $g
* @param int $b
* @return array
*
* @access private
*/
private function rgbToCMYK($r, $g, $b)
{
// RGB to CMY
$C = 1 - ( $r / 255 );
$M = 1 - ( $g / 255 );
$Y = 1 - ( $b / 255 );
//Where CMYK and CMY values = 0 ÷ 1
$var_K = 1;
if ( $C < $var_K ) $var_K = $C;
if ( $M < $var_K ) $var_K = $M;
if ( $Y < $var_K ) $var_K = $Y;
if ( $var_K == 1 ) { //Black
$C = 0;
$M = 0;
$Y = 0;
}
else {
$C = ( $C - $var_K ) / ( 1 - $var_K );
$M = ( $M - $var_K ) / ( 1 - $var_K );
$Y = ( $Y - $var_K ) / ( 1 - $var_K );
}
// $K ( black value )
$K = $var_K;
return array($C, $M, $Y, $K);
}// ef
/**
* Converts CMYK to RGB
* First converts from CMYK to CMY
* then performs the convertion between CMY and RGB
*
* Algorithm found at easyrgb http://www.easyrgb.com/ ( pseudocode )
* Here's my php implementation
*
* @param float $C
* @param float $M
* @param float $Y
* @param float $K
* @return array
*
* @access private
*/
private function cmykToRGB($C, $M, $Y, $K)
{
// : CMYK and CMY values are 0 ÷ 1
// : CMYK to CMY
$C = doubleval( $C * ( 1 - $K ) + $K );
$M = doubleval( $M * ( 1 - $K ) + $K );
$Y = doubleval( $Y * ( 1 - $K ) + $K );
// : CMY to RGB
$R = ( 1 - $C ) * 255;
$G = ( 1 - $M ) * 255;
$B = ( 1 - $Y ) * 255;
return array($R, $G, $B);
}// ef
/**
* Allows multiple manipulations to take effect with a single function call
* Optional args for applyFilter are hardcoded here
* For custom behaviours use applyFilter function alone
* A funny method isn't it? Enjoy :)
*
* @param string $combo_code
* @param int $angle rotation angle
* @access public
*
* @example $istance->$a->rcombo("introtneg", 90);
* @example $istance->$a->rcombo("bluebrig");
*/
public function rcombo($combo_code = "", $angle = 0)
{
// : We may have to dinamically allocate some extra memory
$this->alloc();
if(eregi("int", $combo_code))
$this->interlace(1);
if(eregi("rot", $combo_code))
$this->rotate($angle);
if(eregi("neg", $combo_code))
$this->applyFilter(0);
if(eregi("gray", $combo_code))
$this->applyFilter(1);
if(eregi("emb", $combo_code))
$this->applyFilter(6);
if(eregi("blue", $combo_code))
$this->applyFilter(4, 0, 0, 255);
if(eregi("red", $combo_code))
$this->applyFilter(4, 255, 0, 0);
if(eregi("green", $combo_code))
$this->applyFilter(4, 0, 255, 0);
if(eregi("smo", $combo_code))
$this->applyFilter(10, 50);
if(eregi("blur", $combo_code))
$this->applyFilter(7);
if(eregi("brig", $combo_code))
$this->applyFilter(2, 50);
if(eregi("edge", $combo_code))
$this->applyFilter(5);
if(eregi("cont", $combo_code))
$this->applyFilter(3, 50);
if(eregi("sketch", $combo_code))
$this->applyFilter(9);
if(eregi("sepia", $combo_code))
$this->sepia();
}// ef
/**
* Saves the brand new image to filesystem
*
* @param string $suffix string will be appended at the image name
* @access public
*
* @example $this->save('_rotated') => filename will be : imagename_rotated.ext
*/
public function save( $suffix = "" )
{
global $debug_mode;
// : Saving image according to extension
switch($this->ext)
{
// imagejpeg has a third parameter ( int quality :: hard coded here value=100)
default:
case "jpg":
case "jpeg":
imagejpeg($this->im_resource, $this->new_name . $suffix . "." . $this->ext, 100);
break;
case "gif":
imagegif($this->im_resource, $this->new_name . $suffix . "." . $this->ext);
break;
case "png":
imagepng($this->im_resource, $this->new_name . $suffix . "." . $this->ext);
break;
}// ends switch
// :: Free
imagedestroy($this->im_resource);
// : Show errors if any
echo ( empty($this->error_string) && $debug_mode) ? "Op Successfull<br />" : $this->showError();
}// ef
/**
* Alloc as much memory as needed to work with the image
*
* This function inspired by posts appeared on php.net site in the manual page of
* imagecreatefromjpeg function
* Thanks to yaroukh at gmail dot com, Karolis Tamutis karolis.t_AT_gmail.com, JohnBrook at pobox dot com
*
* @access private
*/
private function alloc()
{
// : How many bytes we'll need to allocate
$memory_needed = !empty($this->memory_needed) ? $this->memory_needed : $this->predictMemoryUsage();
// : Retrieving data on current memory limit
$current_limit = ceil(ini_get('memory_limit')) * 1024 * 1024;
$current_usage = ceil(memory_get_usage());
// : New limit
$new_limit = $current_limit + ceil(($current_usage + $memory_needed - $current_limit ));
if(($new_limit > $current_limit))
{
if(!($new_limit > self::_UPPERLIMIT))
{
// : Malloc
ini_set( 'memory_limit', ceil($new_limit/self::_MB) . 'M' );
}
else
{
$this->setError( sprintf(_MEM_LIMIT_REACHED, $new_limit), 1);
}
}// endif
}// ef
/**
* Computes memory needed forn performing operations
*
* This function inspired by posts appeared on php.net site in the manual page of
* imagecreatefromjpeg function
* Thanks to yaroukh at gmail dot com, Karolis Tamutis karolis.t_AT_gmail.com, JohnBrook at pobox dot com
*
* @return int
* @access private
*
*/
private function predictMemoryUsage()
{
// : Computing memory needed
$memory_needed = ceil( ( $this->im_resource_info[0]
* $this->im_resource_info[1]
* $this->im_resource_info['bits']
* $this->im_resource_info['channels'] / 8
+ self::_64K
)
* self::_TFACTOR
);
return $memory_needed;
}// ef
/**
* Appends data ($er_msg) to the $error_string Class var
* If code is set to 1 execution is stopped
*
* @param string $er_msg
* @param int $code
*
* @access private
*/
private function setError($er_msg = "", $code = 0)
{
$this->error_string .= $er_msg . " ";
// If code is 1 execution must be stopped
// Error is fatal
if( $code === 1 )
{
$this->showError();
exit();
}
}// ef
/**
* Shows Current Error String
*
* @access public
*
*/
public function showError()
{
global $debug_mode;
if( $debug_mode )
echo $this->error_string;
}// ef
/**
* Shows a PNG image or a string with an error message
* if something has gone wrong during the image creation
*
* @access private
*/
private function showImgError()
{
// : Image size is a configuration option
global $er_image_w;
global $er_image_h;
// :: Creating an empty image
$im = imagecreate($er_image_w, $er_image_h);
// : Color Allocation
$bg_color = imagecolorallocate($im, 160, 0, 0);// a kind of red
$text_color = imagecolorallocate($im, 240, 240, 240);// a kind of white
// : Painting the background rectangle with $bg_color
imagefilledrectangle($im, 0, 0, $er_image_w, $er_image_h, $bg_color);
// : Writing a message on the canvas
imagestring($im, 4, 20, 10, $this->error_string, $text_color);
// :: Output, checks if headers are already sent
if(!headers_sent())
{
header("Content-type: image/png");
if(!@imagepng($im)) { $this->showError(); }
}
else { echo $this->showError(); }
// :: Free
imagedestroy($im);
}// ef
/**
* Class Destructor
*
* @access public
*/
public function __destruct()
{
// If save() has not been called let's destroy the image resource
if($this->im_resource)
{
@imagedestroy($this->im_resource);
}
}// ef
}// END OF CLASS
?>
|