<?php
//
// class.cropcanvas.php
// version 1.2.0, 26th November, 2003
//
// Description
//
// This is a class allows you to crop an image in a variety of ways.
// You can crop in an absolute or relative way (to a certain size or
// by a certain size), both as a pixel number or a percentage. You
// can also save or display the cropped image. The cropping can be
// done in 9 different positions: top left, top, top right, left,
// centre, right, bottom left, bottom, or bottom right. Or you can
// crop automatically based on a threshold limit. The original
// image can be loaded from the file system or from a string (for
// example, data returned from a database.)
//
// Author
//
// Andrew Collington, 2003
// php@amnuts.com, http://php.amnuts.com/
//
//
// Feedback
//
// There is message board at the following address:
//
// http://php.amnuts.com/forums/index.php
//
// Please use that to post up any comments, questions, bug reports, etc. You
// can also use the board to show off your use of the script.
//
// Support
//
// If you like this script, or any of my others, then please take a moment
// to consider giving a donation. This will encourage me to make updates and
// create new scripts which I would make available to you. If you would like
// to donate anything, then there is a link from my website to PayPal.
//
// Example of use
//
// require 'class.cropcanvas.php';
// $cc = new canvasCrop();
//
// $cc->loadImage('original1.png');
// $cc->cropBySize(100, 100, ccBOTTOMRIGHT);
// $cc->saveImage('final1.png');
//
// $cc->flushImages();
//
// $cc->loadImage('original2.png');
// $cc->cropByPercent(15, 50, ccCENTER);
// $cc->saveImage('final2.jpg', 90);
//
// $cc->flushImages();
//
// $cc->loadImage('original3.png');
// $cc->cropToDimensions(67, 37, 420, 255);
// $cc->showImage('png');
//
define("ccTOPLEFT", 0); define("ccTOP", 1);
define("ccTOPRIGHT", 2); define("ccLEFT", 3); define("ccCENTRE", 4); define("ccCENTER", 4); define("ccRIGHT", 5); define("ccBOTTOMLEFT", 6); define("ccBOTTOM", 7); define("ccBOTTOMRIGHT", 8);
class canvasCrop {
var $_imgOrig;
var $_imgFinal;
var $_showDebug;
var $_gdVersion;
/**
* @return canvasCrop
* @param bool $debug
* @desc Class initializer
*/
function canvasCrop($debug = false)
{
$this->_showDebug = ($debug ? true : false);
$this->_gdVersion = (function_exists('imagecreatetruecolor')) ? 2 : 1;
}
/**
* @return bool
* @param string $filename
* @desc Load an image from the file system - method based on file extension
*/
function loadImage($filename)
{
if (!@file_exists($filename))
{
$this->_debug('loadImage', "The supplied file name '$filename' does not point to a readable file.");
return false;
}
$ext = strtolower($this->_getExtension($filename));
$func = "imagecreatefrom$ext";
if (!@function_exists($func))
{
$this->_debug('loadImage', "That file cannot be loaded with the function '$func'.");
return false;
}
$this->_imgOrig = @$func($filename);
if ($this->_imgOrig == null)
{
$this->_debug('loadImage', 'The image could not be loaded.');
return false;
}
return true;
}
/**
* @return bool
* @param string $string
* @desc Load an image from a string (eg. from a database table)
*/
function loadImageFromString($string)
{
$this->_imgOrig = @ImageCreateFromString($string);
if (!$this->_imgOrig)
{
$this->_debug('loadImageFromString', 'The image could not be loaded.');
return false;
}
return true;
}
/**
* @return bool
* @param string $filename
* @param int $quality
* @desc Save the cropped image
*/
function saveImage($filename, $quality = 100)
{
if ($this->_imgFinal == null)
{
$this->_debug('saveImage', 'There is no processed image to save.');
return false;
}
$ext = strtolower($this->_getExtension($filename));
$func = "image$ext";
if (!@function_exists($func))
{
$this->_debug('saveImage', "That file cannot be saved with the function '$func'.");
return false;
}
$saved = false;
if ($ext == 'png') $saved = $func($this->_imgFinal, $filename);
if ($ext == 'jpeg') $saved = $func($this->_imgFinal, $filename, $quality);
if ($saved == false)
{
$this->_debug('saveImage', "Could not save the output file '$filename' as a $ext.");
return false;
}
return true;
}
/**
* @return bool
* @param string $type
* @param int $quality
* @desc Shows the cropped image without any saving
*/
function showImage($type = 'png', $quality = 100)
{
if ($this->_imgFinal == null)
{
$this->_debug('showImage', 'There is no processed image to show.');
return false;
}
if ($type == 'png')
{
echo @ImagePNG($this->_imgFinal);
return true;
}
else if ($type == 'jpg' || $type == 'jpeg')
{
echo @ImageJPEG($this->_imgFinal, '', $quality);
return true;
}
else
{
$this->_debug('showImage', "Could not show the output file as a $type.");
return false;
}
}
/**
* @return int
* @param int $x
* @param int $y
* @param int $position
* @desc Determines the dimensions to crop to if using the 'crop by size' method
*/
function cropBySize($x, $y, $position = ccCENTRE)
{
if ($x == 0)
{
$nx = @ImageSX($this->_imgOrig);
}
else
{
$nx = @ImageSX($this->_imgOrig) - $x;
}
if ($y == 0)
{
$ny = @ImageSY($this->_imgOrig);
}
else
{
$ny = @ImageSY($this->_imgOrig) - $y;
}
return ($this->_cropSize(-1, -1, $nx, $ny, $position, 'cropBySize'));
}
/**
* @return int
* @param int $x
* @param int $y
* @param int $position
* @desc Determines the dimensions to crop to if using the 'crop to size' method
*/
function cropToSize($x, $y, $position = ccCENTRE)
{
if ($x == 0) $x = 1;
if ($y == 0) $y = 1;
return ($this->_cropSize(-1, -1, $x, $y, $position, 'cropToSize'));
}
/**
* @return int
* @param int $sx
* @param int $sy
* @param int $ex
* @param int $ey
* @desc Determines the dimensions to crop to if using the 'crop to dimensions' method
*/
function cropToDimensions($sx, $sy, $ex, $ey)
{
$nx = abs($ex - $sx);
$ny = abs($ey - $sy);
return ($this->_cropSize($sx, $sy, $nx, $ny, $position, 'cropToDimensions'));
}
/**
* @return int
* @param int $percentx
* @param int $percenty
* @param int $position
* @desc Determines the dimensions to crop to if using the 'crop by percentage' method
*/
function cropByPercent($percentx, $percenty, $position = ccCENTRE)
{
if ($percentx == 0)
{
$nx = @ImageSX($this->_imgOrig);
}
else
{
$nx = @ImageSX($this->_imgOrig) - (($percentx / 100) * @ImageSX($this->_imgOrig));
}
if ($percenty == 0)
{
$ny = @ImageSY($this->_imgOrig);
}
else
{
$ny = @ImageSY($this->_imgOrig) - (($percenty / 100) * @ImageSY($this->_imgOrig));
}
return ($this->_cropSize(-1, -1, $nx, $ny, $position, 'cropByPercent'));
}
/**
* @return int
* @param int $percentx
* @param int $percenty
* @param int $position
* @desc Determines the dimensions to crop to if using the 'crop to percentage' method
*/
function cropToPercent($percentx, $percenty, $position = ccCENTRE)
{
if ($percentx == 0)
{
$nx = @ImageSX($this->_imgOrig);
}
else
{
$nx = ($percentx / 100) * @ImageSX($this->_imgOrig);
}
if ($percenty == 0)
{
$ny = @ImageSY($this->_imgOrig);
}
else
{
$ny = ($percenty / 100) * @ImageSY($this->_imgOrig);
}
return ($this->_cropSize(-1, -1, $nx, $ny, $position, 'cropByPercent'));
}
/**
* @return bool
* @param int $threshold
* @desc Determines the dimensions to crop to if using the 'automatic crop by threshold' method
*/
function cropByAuto($threshold = 254)
{
if ($threshold < 0) $threshold = 0;
if ($threshold > 255) $threshold = 255;
$sizex = @ImageSX($this->_imgOrig);
$sizey = @ImageSY($this->_imgOrig);
$sx = $sy = $ex = $ey = -1;
for ($y = 0; $y < $sizey; $y++)
{
for ($x = 0; $x < $sizex; $x++)
{
if ($threshold >= $this->_getThresholdValue($this->_imgOrig, $x, $y))
{
if ($sy == -1) $sy = $y;
else $ey = $y;
if ($sx == -1) $sx = $x;
else
{
if ($x < $sx) $sx = $x;
else if ($x > $ex) $ex = $x;
}
}
}
}
$nx = abs($ex - $sx);
$ny = abs($ey - $sy);
return ($this->_cropSize($sx, $sy, $nx, $ny, ccTOPLEFT, 'cropByAuto'));
}
/**
* @return void
* @desc Destroy the resources used by the images
*/
function flushImages()
{
@ImageDestroy($this->_imgOrig);
@ImageDestroy($this->_imgFinal);
$this->_imgOrig = $this->_imgFinal = null;
}
/**
* @return bool
* @param int $ox Original image width
* @param int $oy Original image height
* @param int $nx New width
* @param int $ny New height
* @param int $position Where to place the crop
* @param string $function Name of the calling function
* @desc Creates the cropped image based on passed parameters
*/
function _cropSize($ox, $oy, $nx, $ny, $position, $function)
{
if ($this->_imgOrig == null)
{
$this->_debug($function, 'The original image has not been loaded.');
return false;
}
if (($nx <= 0) || ($ny <= 0))
{
$this->_debug($function, 'The image could not be cropped because the size given is not valid.');
return false;
}
if (($nx > @ImageSX($this->_imgOrig)) || ($ny > @ImageSY($this->_imgOrig)))
{
$this->_debug($function, 'The image could not be cropped because the size given is larger than the original image.');
return false;
}
if ($ox == -1 || $oy == -1)
{
list($ox, $oy) = $this->_getCopyPosition($nx, $ny, $position);
}
if ($this->_gdVersion == 2)
{
$this->_imgFinal = @ImageCreateTrueColor($nx, $ny);
@ImageCopyResampled($this->_imgFinal, $this->_imgOrig, 0, 0, $ox, $oy, $nx, $ny, $nx, $ny);
}
else
{
$this->_imgFinal = @ImageCreate($nx, $ny);
@ImageCopyResized($this->_imgFinal, $this->_imgOrig, 0, 0, $ox, $oy, $nx, $ny, $nx, $ny);
}
return true;
}
/**
* @return array
* @param int $nx
* @param int $ny
* @param int $position
* @desc Determines dimensions of the crop
*/
function _getCopyPosition($nx, $ny, $position)
{
$ox = @ImageSX($this->_imgOrig);
$oy = @ImageSY($this->_imgOrig);
switch($position)
{
case ccTOPLEFT:
return array(0, 0);
case ccTOP:
return array(ceil(($ox - $nx) / 2), 0);
case ccTOPRIGHT:
return array(($ox - $nx), 0);
case ccLEFT:
return array(0, ceil(($oy - $ny) / 2));
case ccCENTRE:
return array(ceil(($ox - $nx) / 2), ceil(($oy - $ny) / 2));
case ccRIGHT:
return array(($ox - $nx), ceil(($oy - $ny) / 2));
case ccBOTTOMLEFT:
return array(0, ($oy - $ny));
case ccBOTTOM:
return array(ceil(($ox - $nx) / 2), ($oy - $ny));
case ccBOTTOMRIGHT:
return array(($ox - $nx), ($oy - $ny));
}
}
/**
* @return float
* @param resource $im
* @param int $x
* @param int $y
* @desc Determines the intensity value of a pixel at the passed co-ordinates
*/
function _getThresholdValue($im, $x, $y)
{
$rgb = ImageColorAt($im, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$intensity = ($r + $g + $b) / 3;
return $intensity;
}
/**
* @return string
* @param string $filename
* @desc Get the extension of a file name
*/
function _getExtension($filename)
{
$ext = @strtolower(@substr($filename, (@strrpos($filename, ".") ? @strrpos($filename, ".") + 1 : @strlen($filename)), @strlen($filename)));
return ($ext == 'jpg') ? 'jpeg' : $ext;
}
/**
* @return void
* @param string $function
* @param string $string
* @desc Shows debugging information
*/
function _debug($function, $string)
{
if ($this->_showDebug)
{
echo "<p><strong style="color:#FF0000">Error in function $function:</strong> $string</p>n";
}
}
/**
* @return array
* @desc Try to ascertain what the version of GD being used is, based on phpinfo output
*/
function _getGDVersion()
{
static $version = array();
if (empty($version))
{
ob_start();
phpinfo();
$buffer = ob_get_contents();
ob_end_clean();
if (preg_match("|<B>GD Version</B></td><TD ALIGN="left">([^<]*)</td>|i", $buffer, $matches))
{
$version = explode('.', $matches[1]);
}
else if (preg_match("|GD Version </td><td class="v">bundled (([^ ]*)|i", $buffer, $matches))
{
$version = explode('.', $matches[1]);
}
else if (preg_match("|GD Version </td><td class="v">([^ ]*)|i", $buffer, $matches))
{
$version = explode('.', $matches[1]);
}
}
return $version;
}
}
?>
|
|