ZwiiCMS/core/vendor/filemanager/include/php_image_magician.php
2018-04-02 08:29:19 +02:00

3786 lines
96 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
# ========================================================================#
#
# This work is licensed under the Creative Commons Attribution 3.0 Unported
# License. To view a copy of this license,
# visit http://creativecommons.org/licenses/by/3.0/ or send a letter to
# Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
# 94041, USA.
#
# All rights reserved.
#
# Author: Jarrod Oberto
# Version: 1.5.1
# Date: 10-05-11
# Purpose: Provide tools for image manipulation using GD
# Param In: See functions.
# Param Out: Produces a resized image
# Requires : Requires PHP GD library.
# Usage Example:
# include("lib/php_image_magician.php");
# $magicianObj = new resize('images/car.jpg');
# $magicianObj -> resizeImage(150, 100, 0);
# $magicianObj -> saveImage('images/car_small.jpg', 100);
#
# - See end of doc for more examples -
#
# Supported file types include: jpg, png, gif, bmp, psd (read)
#
#
#
# The following functions are taken from phpThumb() [available from
# http://phpthumb.sourceforge.net], and are used with written permission
# from James Heinrich.
# - GD2BMPstring
# - GetPixelColor
# - LittleEndian2String
#
# The following functions are from Marc Hibbins and are used with written
# permission (are also under the Attribution-ShareAlike
# [http://creativecommons.org/licenses/by-sa/3.0/] license.
# -
#
# PhpPsdReader is used with written permission from Tim de Koning.
# [http://www.kingsquare.nl/phppsdreader]
#
#
#
# Modificatoin history
# Date Initials Ver Description
# 10-05-11 J.C.O 0.0 Initial build
# 01-06-11 J.C.O 0.1.1 * Added reflections
# * Added Rounded corners
# * You can now use PNG interlacing
# * Added shadow
# * Added caption box
# * Added vintage filter
# * Added dynamic image resizing (resize on the fly)
# * minor bug fixes
# 05-06-11 J.C.O 0.1.1.1 * Fixed undefined variables
# 17-06-11 J.C.O 0.1.2 * Added image_batch_class.php class
# * Minor bug fixes
# 26-07-11 J.C.O 0.1.4 * Added support for external images
# * Can now set the crop poisition
# 03-08-11 J.C.O 0.1.5 * Added reset() method to reset resource to
# original input file.
# * Added method addTextToCaptionBox() to
# simplify adding text to a caption box.
# * Added experimental writeIPTC. (not finished)
# * Added experimental readIPTC. (not finished)
# 11-08-11 J.C.O * Added initial border presets.
# 30-08-11 J.C.O * Added 'auto' crop option to crop portrait
# images near the top.
# 08-09-11 J.C.O * Added cropImage() method to allow standalone
# cropping.
# 17-09-11 J.C.O * Added setCropFromTop() set method - set the
# percentage to crop from the top when using
# crop 'auto' option.
# * Added setTransparency() set method - allows you
# to turn transparency off (like when saving
# as a jpg).
# * Added setFillColor() set method - set the
# background color to use instead of transparency.
# 05-11-11 J.C.O 0.1.5.1 * Fixed interlacing option
# 0-07-12 J.C.O 1.0
#
# Known issues & Limitations:
# -------------------------------
# Not so much an issue, the image is destroyed on the deconstruct rather than
# when we have finished with it. The reason for this is that we don't know
# when we're finished with it as you can both save the image and display
# it directly to the screen (imagedestroy($this->imageResized))
#
# Opening BMP files is slow. A test with 884 bmp files processed in a loop
# takes forever - over 5 min. This test inlcuded opening the file, then
# getting and displaying its width and height.
#
# $forceStretch:
# -------------------------------
# On by default.
# $forceStretch can be disabled by calling method setForceStretch with false
# parameter. If disabled, if an images original size is smaller than the size
# specified by the user, the original size will be used. This is useful when
# dealing with small images.
#
# If enabled, images smaller than the size specified will be stretched to
# that size.
#
# Tips:
# -------------------------------
# * If you're resizing a transparent png and saving it as a jpg, set
# $keepTransparency to false with: $magicianObj->setTransparency(false);
#
# FEATURES:
# * EASY TO USE
# * BMP SUPPORT (read & write)
# * PSD (photoshop) support (read)
# * RESIZE IMAGES
# - Preserve transparency (png, gif)
# - Apply sharpening (jpg) (requires PHP >= 5.1.0)
# - Set image quality (jpg, png)
# - Resize modes:
# - exact size
# - resize by width (auto height)
# - resize by height (auto width)
# - auto (automatically determine the best of the above modes to use)
# - crop - resize as best as it can then crop the rest
# - Force stretching of smaller images (upscale)
# * APPLY FILTERS
# - Convert to grey scale
# - Convert to black and white
# - Convert to sepia
# - Convert to negative
# * ROTATE IMAGES
# - Rotate using predefined "left", "right", or "180"; or any custom degree amount
# * EXTRACT EXIF DATA (requires exif module)
# - make
# - model
# - date
# - exposure
# - aperture
# - f-stop
# - iso
# - focal length
# - exposure program
# - metering mode
# - flash status
# - creator
# - copyright
# * ADD WATERMARK
# - Specify exact x, y placement
# - Or, specify using one of the 9 pre-defined placements such as "tl"
# (for top left), "m" (for middle), "br" (for bottom right)
# - also specify padding from edge amount (optional).
# - Set opacity of watermark (png).
# * ADD BORDER
# * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff)
# * SAVE IMAGE OR OUTPUT TO SCREEN
#
#
# ========================================================================#
class imageLib {
private $fileName;
private $image;
protected $imageResized;
private $widthOriginal; # Always be the original width
private $heightOriginal;
private $width; # Current width (width after resize)
private $height;
private $imageSize;
private $fileExtension;
private $debug = true;
private $errorArray = array();
private $forceStretch = true;
private $aggresiveSharpening = false;
private $transparentArray = array( '.png', '.gif' );
private $keepTransparency = true;
private $fillColorArray = array( 'r' => 255, 'g' => 255, 'b' => 255 );
private $sharpenArray = array( 'jpg' );
private $psdReaderPath;
private $filterOverlayPath;
private $isInterlace;
private $captionBoxPositionArray = array();
private $fontDir = 'fonts';
private $cropFromTopPercent = 10;
## --------------------------------------------------------
function __construct($fileName)
# Author: Jarrod Oberto
# Date: 27-02-08
# Purpose: Constructor
# Param in: $fileName: File name and path.
# Param out: n/a
# Reference:
# Notes:
#
{
if ( ! $this->testGDInstalled())
{
if ($this->debug)
{
throw new Exception('The GD Library is not installed.');
}
else
{
throw new Exception();
}
};
$this->initialise();
// *** Save the image file name. Only store this incase you want to display it
$this->fileName = $fileName;
$this->fileExtension = fix_strtolower(strrchr($fileName, '.'));
// *** Open up the file
$this->image = $this->openImage($fileName);
// *** Assign here so we don't modify the original
$this->imageResized = $this->image;
// *** If file is an image
if ($this->testIsImage($this->image))
{
// *** Get width and height
$this->width = imagesx($this->image);
$this->widthOriginal = imagesx($this->image);
$this->height = imagesy($this->image);
$this->heightOriginal = imagesy($this->image);
/* Added 15-09-08
* Get the filesize using this build in method.
* Stores an array of size
*
* $this->imageSize[1] = width
* $this->imageSize[2] = height
* $this->imageSize[3] = width x height
*
*/
$this->imageSize = getimagesize($this->fileName);
}
else
{
$this->errorArray[] = 'File is not an image';
}
}
## --------------------------------------------------------
private function initialise()
{
$this->psdReaderPath = dirname(__FILE__) . '/classPhpPsdReader.php';
$this->filterOverlayPath = dirname(__FILE__) . '/filters';
// *** Set if image should be interlaced or not.
$this->isInterlace = false;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Resize
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = false, $autoRotate = false)
# Author: Jarrod Oberto
# Date: 27-02-08
# Purpose: Resizes the image
# Param in: $newWidth:
# $newHeight:
# $option: 0 / exact = defined size;
# 1 / portrait = keep aspect set height;
# 2 / landscape = keep aspect set width;
# 3 / auto = auto;
# 4 / crop= resize and crop;
#
# $option can also be an array containing options for
# cropping. E.G., array('crop', 'r')
#
# This array only applies to 'crop' and the 'r' refers to
# "crop right". Other value include; tl, t, tr, l, m (default),
# r, bl, b, br, or you can specify your own co-ords (which
# isn't recommended.
#
# $sharpen: true: sharpen (jpg only);
# false: don't sharpen
# Param out: n/a
# Reference:
# Notes: To clarify the $option input:
# 0 = The exact height and width dimensions you set.
# 1 = Whatever height is passed in will be the height that
# is set. The width will be calculated and set automatically
# to a the value that keeps the original aspect ratio.
# 2 = The same but based on the width. We try make the image the
# biggest size we can while stil fitting inside the box size
# 3 = Depending whether the image is landscape or portrait, this
# will automatically determine whether to resize via
# dimension 1,2 or 0
# 4 = Will resize and then crop the image for best fit
#
# forceStretch can be applied to options 1,2,3 and 4
#
{
// *** We can pass in an array of options to change the crop position
$cropPos = 'm';
if (is_array($option) && fix_strtolower($option[0]) == 'crop')
{
$cropPos = $option[1]; # get the crop option
}
else
{
if (strpos($option, '-') !== false)
{
// *** Or pass in a hyphen seperated option
$optionPiecesArray = explode('-', $option);
$cropPos = end($optionPiecesArray);
}
}
// *** Check the option is valid
$option = $this->prepOption($option);
// *** Make sure the file passed in is valid
if ( ! $this->image)
{
if ($this->debug)
{
throw new Exception('file ' . $this->getFileName() . ' is missing or invalid');
}
else
{
throw new Exception();
}
};
// *** Get optimal width and height - based on $option
$dimensionsArray = $this->getDimensions($newWidth, $newHeight, $option);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
// *** Resample - create image canvas of x, y size
$this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
$this->keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized);
imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
// *** If '4', then crop too
if ($option == 4 || $option == 'crop')
{
if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight))
{
$this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
}
}
// *** If Rotate.
if ($autoRotate)
{
$exifData = $this->getExif(false);
if (count($exifData) > 0)
{
switch ($exifData['orientation'])
{
case 8:
$this->imageResized = imagerotate($this->imageResized, 90, 0);
break;
case 3:
$this->imageResized = imagerotate($this->imageResized, 180, 0);
break;
case 6:
$this->imageResized = imagerotate($this->imageResized, -90, 0);
break;
}
}
}
// *** Sharpen image (if jpg and the user wishes to do so)
if ($sharpen && in_array($this->fileExtension, $this->sharpenArray))
{
// *** Sharpen
$this->sharpen();
}
}
## --------------------------------------------------------
public function cropImage($newWidth, $newHeight, $cropPos = 'm')
# Author: Jarrod Oberto
# Date: 08-09-11
# Purpose: Crops the image
# Param in: $newWidth: crop with
# $newHeight: crop height
# $cropPos: Can be any of the following:
# tl, t, tr, l, m, r, bl, b, br, auto
# Or:
# a custom position such as '30x50'
# Param out: n/a
# Reference:
# Notes:
#
{
// *** Make sure the file passed in is valid
if ( ! $this->image)
{
if ($this->debug)
{
throw new Exception('file ' . $this->getFileName() . ' is missing or invalid');
}
else
{
throw new Exception();
}
};
$this->imageResized = $this->image;
$this->crop($this->width, $this->height, $newWidth, $newHeight, $cropPos);
}
## --------------------------------------------------------
private function keepTransparancy($width, $height, $im)
# Author: Jarrod Oberto
# Date: 08-04-11
# Purpose: Keep transparency for png and gif image
# Param in:
# Param out: n/a
# Reference:
# Notes:
#
{
// *** If PNG, perform some transparency retention actions (gif untested)
if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency)
{
imagealphablending($im, false);
imagesavealpha($im, true);
$transparent = imagecolorallocatealpha($im, 255, 255, 255, 127);
imagefilledrectangle($im, 0, 0, $width, $height, $transparent);
}
else
{
$color = imagecolorallocate($im, $this->fillColorArray['r'], $this->fillColorArray['g'], $this->fillColorArray['b']);
imagefilledrectangle($im, 0, 0, $width, $height, $color);
}
}
## --------------------------------------------------------
private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)
# Author: Jarrod Oberto
# Date: 15-09-08
# Purpose: Crops the image
# Param in: $newWidth:
# $newHeight:
# Param out: n/a
# Reference:
# Notes:
#
{
// *** Get cropping co-ordinates
$cropArray = $this->getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
$cropStartX = $cropArray['x'];
$cropStartY = $cropArray['y'];
// *** Crop this bad boy
$crop = imagecreatetruecolor($newWidth, $newHeight);
$this->keepTransparancy($optimalWidth, $optimalHeight, $crop);
imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight, $newWidth, $newHeight);
$this->imageResized = $crop;
// *** Set new width and height to our variables
$this->width = $newWidth;
$this->height = $newHeight;
}
## --------------------------------------------------------
private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos = 'm')
#
# Author: Jarrod Oberto
# Date: July 11
# Purpose: Set the cropping area.
# Params in:
# Params out: (array) the crop x and y co-ordinates.
# Notes: When specifying the exact pixel crop position (eg 10x15), be
# very careful as it's easy to crop out of the image leaving
# black borders.
#
{
$pos = fix_strtolower($pos);
// *** If co-ords have been entered
if (strstr($pos, 'x'))
{
$pos = str_replace(' ', '', $pos);
$xyArray = explode('x', $pos);
list($cropStartX, $cropStartY) = $xyArray;
}
else
{
switch ($pos)
{
case 'tl':
$cropStartX = 0;
$cropStartY = 0;
break;
case 't':
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
$cropStartY = 0;
break;
case 'tr':
$cropStartX = $optimalWidth - $newWidth;
$cropStartY = 0;
break;
case 'l':
$cropStartX = 0;
$cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
break;
case 'm':
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
$cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
break;
case 'r':
$cropStartX = $optimalWidth - $newWidth;
$cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
break;
case 'bl':
$cropStartX = 0;
$cropStartY = $optimalHeight - $newHeight;
break;
case 'b':
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
$cropStartY = $optimalHeight - $newHeight;
break;
case 'br':
$cropStartX = $optimalWidth - $newWidth;
$cropStartY = $optimalHeight - $newHeight;
break;
case 'auto':
// *** If image is a portrait crop from top, not center. v1.5
if ($optimalHeight > $optimalWidth)
{
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
$cropStartY = ($this->cropFromTopPercent / 100) * $optimalHeight;
}
else
{
// *** Else crop from the center
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
$cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
}
break;
default:
// *** Default to center
$cropStartX = ($optimalWidth / 2) - ($newWidth / 2);
$cropStartY = ($optimalHeight / 2) - ($newHeight / 2);
break;
}
}
return array( 'x' => $cropStartX, 'y' => $cropStartY );
}
## --------------------------------------------------------
private function getDimensions($newWidth, $newHeight, $option)
# Author: Jarrod Oberto
# Date: 17-11-09
# Purpose: Get new image dimensions based on user specificaions
# Param in: $newWidth:
# $newHeight:
# Param out: Array of new width and height values
# Reference:
# Notes: If $option = 3 then this function is call recursivly
#
# To clarify the $option input:
# 0 = The exact height and width dimensions you set.
# 1 = Whatever height is passed in will be the height that
# is set. The width will be calculated and set automatically
# to a the value that keeps the original aspect ratio.
# 2 = The same but based on the width.
# 3 = Depending whether the image is landscape or portrait, this
# will automatically determine whether to resize via
# dimension 1,2 or 0.
# 4 = Resize the image as much as possible, then crop the
# remainder.
{
switch (strval($option))
{
case '0':
case 'exact':
$optimalWidth = $newWidth;
$optimalHeight = $newHeight;
break;
case '1':
case 'portrait':
$dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
break;
case '2':
case 'landscape':
$dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
break;
case '3':
case 'auto':
$dimensionsArray = $this->getSizeByAuto($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
break;
case '4':
case 'crop':
$dimensionsArray = $this->getOptimalCrop($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
break;
}
return array( 'optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight );
}
## --------------------------------------------------------
private function getSizeByFixedHeight($newWidth, $newHeight)
{
// *** If forcing is off...
if ( ! $this->forceStretch)
{
// *** ...check if actual height is less than target height
if ($this->height < $newHeight)
{
return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height );
}
}
$ratio = $this->width / $this->height;
$newWidth = $newHeight * $ratio;
//return $newWidth;
return array( 'optimalWidth' => $newWidth, 'optimalHeight' => $newHeight );
}
## --------------------------------------------------------
private function getSizeByFixedWidth($newWidth, $newHeight)
{
// *** If forcing is off...
if ( ! $this->forceStretch)
{
// *** ...check if actual width is less than target width
if ($this->width < $newWidth)
{
return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height );
}
}
$ratio = $this->height / $this->width;
$newHeight = $newWidth * $ratio;
//return $newHeight;
return array( 'optimalWidth' => $newWidth, 'optimalHeight' => $newHeight );
}
## --------------------------------------------------------
private function getSizeByAuto($newWidth, $newHeight)
# Author: Jarrod Oberto
# Date: 19-08-08
# Purpose: Depending on the height, choose to resize by 0, 1, or 2
# Param in: The new height and new width
# Notes:
#
{
// *** If forcing is off...
if ( ! $this->forceStretch)
{
// *** ...check if actual size is less than target size
if ($this->width < $newWidth && $this->height < $newHeight)
{
return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height );
}
}
if ($this->height < $this->width)
// *** Image to be resized is wider (landscape)
{
//$optimalWidth = $newWidth;
//$optimalHeight= $this->getSizeByFixedWidth($newWidth);
$dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
}
elseif ($this->height > $this->width)
// *** Image to be resized is taller (portrait)
{
//$optimalWidth = $this->getSizeByFixedHeight($newHeight);
//$optimalHeight= $newHeight;
$dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
}
else
// *** Image to be resizerd is a square
{
if ($newHeight < $newWidth)
{
//$optimalWidth = $newWidth;
//$optimalHeight= $this->getSizeByFixedWidth($newWidth);
$dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
}
else
{
if ($newHeight > $newWidth)
{
//$optimalWidth = $this->getSizeByFixedHeight($newHeight);
//$optimalHeight= $newHeight;
$dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
$optimalWidth = $dimensionsArray['optimalWidth'];
$optimalHeight = $dimensionsArray['optimalHeight'];
}
else
{
// *** Sqaure being resized to a square
$optimalWidth = $newWidth;
$optimalHeight = $newHeight;
}
}
}
return array( 'optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight );
}
## --------------------------------------------------------
private function getOptimalCrop($newWidth, $newHeight)
# Author: Jarrod Oberto
# Date: 17-11-09
# Purpose: Get optimal crop dimensions
# Param in: width and height as requested by user (fig 3)
# Param out: Array of optimal width and height (fig 2)
# Reference:
# Notes: The optimal width and height return are not the same as the
# same as the width and height passed in. For example:
#
#
# |-----------------| |------------| |-------|
# | | => |**| |**| => | |
# | | |**| |**| | |
# | | |------------| |-------|
# |-----------------|
# original optimal crop
# size size size
# Fig 1 2 3
#
# 300 x 250 150 x 125 150 x 100
#
# The optimal size is the smallest size (that is closest to the crop size)
# while retaining proportion/ratio.
#
# The crop size is the optimal size that has been cropped on one axis to
# make the image the exact size specified by the user.
#
# * represent cropped area
#
{
// *** If forcing is off...
if ( ! $this->forceStretch)
{
// *** ...check if actual size is less than target size
if ($this->width < $newWidth && $this->height < $newHeight)
{
return array( 'optimalWidth' => $this->width, 'optimalHeight' => $this->height );
}
}
$heightRatio = $this->height / $newHeight;
$widthRatio = $this->width / $newWidth;
if ($heightRatio < $widthRatio)
{
$optimalRatio = $heightRatio;
}
else
{
$optimalRatio = $widthRatio;
}
$optimalHeight = round($this->height / $optimalRatio);
$optimalWidth = round($this->width / $optimalRatio);
return array( 'optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight );
}
## --------------------------------------------------------
private function sharpen()
# Author: Jarrod Oberto
# Date: 08 04 2011
# Purpose: Sharpen image
# Param in: n/a
# Param out: n/a
# Reference:
# Notes:
# Credit: Incorporates Joe Lencioni (August 6, 2008) code
{
if (version_compare(PHP_VERSION, '5.1.0') >= 0)
{
// ***
if ($this->aggresiveSharpening)
{ # A more aggressive sharpening solution
$sharpenMatrix = array( array( -1, -1, -1 ),
array( -1, 16, -1 ),
array( -1, -1, -1 ) );
$divisor = 8;
$offset = 0;
imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
}
else # More subtle and personally more desirable
{
$sharpness = $this->findSharp($this->widthOriginal, $this->width);
$sharpenMatrix = array(
array( -1, -2, -1 ),
array( -2, $sharpness + 12, -2 ), //Lessen the effect of a filter by increasing the value in the center cell
array( -1, -2, -1 )
);
$divisor = $sharpness; // adjusts brightness
$offset = 0;
imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
}
}
else
{
if ($this->debug)
{
throw new Exception('Sharpening required PHP 5.1.0 or greater.');
}
}
}
## --------------------------------------------------------
private function sharpen2($level)
{
$sharpenMatrix = array(
array( $level, $level, $level ),
array( $level, (8 * $level) + 1, $level ), //Lessen the effect of a filter by increasing the value in the center cell
array( $level, $level, $level )
);
}
## --------------------------------------------------------
private function findSharp($orig, $final)
# Author: Ryan Rud (http://adryrun.com)
# Purpose: Find optimal sharpness
# Param in: n/a
# Param out: n/a
# Reference:
# Notes:
#
{
$final = $final * (750.0 / $orig);
$a = 52;
$b = -0.27810650887573124;
$c = .00047337278106508946;
$result = $a + $b * $final + $c * $final * $final;
return max(round($result), 0);
}
## --------------------------------------------------------
private function prepOption($option)
# Author: Jarrod Oberto
# Purpose: Prep option like change the passed in option to lowercase
# Param in: (str/int) $option: eg. 'exact', 'crop'. 0, 4
# Param out: lowercase string
# Reference:
# Notes:
#
{
if (is_array($option))
{
if (fix_strtolower($option[0]) == 'crop' && count($option) == 2)
{
return 'crop';
}
else
{
throw new Exception('Crop resize option array is badly formatted.');
}
}
else
{
if (strpos($option, 'crop') !== false)
{
return 'crop';
}
}
if (is_string($option))
{
return fix_strtolower($option);
}
return $option;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Presets
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
#
# Preset are pre-defined templates you can apply to your image.
#
# These are inteded to be applied to thumbnail images.
#
public function borderPreset($preset)
{
switch ($preset)
{
case 'simple':
$this->addBorder(7, '#fff');
$this->addBorder(6, '#f2f1f0');
$this->addBorder(2, '#fff');
$this->addBorder(1, '#ccc');
break;
default:
break;
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Draw border
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function addBorder($thickness = 1, $rgbArray = array( 255, 255, 255 ))
# Author: Jarrod Oberto
# Date: 05-05-11
# Purpose: Add a border to the image
# Param in:
# Param out:
# Reference:
# Notes: This border is added to the INSIDE of the image
#
{
if ($this->imageResized)
{
$rgbArray = $this->formatColor($rgbArray);
$r = $rgbArray['r'];
$g = $rgbArray['g'];
$b = $rgbArray['b'];
$x1 = 0;
$y1 = 0;
$x2 = ImageSX($this->imageResized) - 1;
$y2 = ImageSY($this->imageResized) - 1;
$rgbArray = ImageColorAllocate($this->imageResized, $r, $g, $b);
for ($i = 0; $i < $thickness; $i++)
{
ImageRectangle($this->imageResized, $x1++, $y1++, $x2--, $y2--, $rgbArray);
}
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Gray Scale
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function greyScale()
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Make image greyscale
# Param in: n/a
# Param out:
# Reference:
# Notes:
#
{
if ($this->imageResized)
{
imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
}
}
## --------------------------------------------------------
public function greyScaleEnhanced()
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Make image greyscale
# Param in: n/a
# Param out:
# Reference:
# Notes:
#
{
if ($this->imageResized)
{
imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2);
$this->sharpen($this->width);
}
}
## --------------------------------------------------------
public function greyScaleDramatic()
# Alias of gd_filter_monopin
{
$this->gd_filter_monopin();
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Black 'n White
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function blackAndWhite()
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Make image black and white
# Param in: n/a
# Param out:
# Reference:
# Notes:
#
{
if ($this->imageResized)
{
imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000);
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Negative
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function negative()
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Make image negative
# Param in: n/a
# Param out:
# Reference:
# Notes:
#
{
if ($this->imageResized)
{
imagefilter($this->imageResized, IMG_FILTER_NEGATE);
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Sepia
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function sepia()
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Make image sepia
# Param in: n/a
# Param out:
# Reference:
# Notes:
#
{
if ($this->imageResized)
{
imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10);
imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20);
imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15);
}
}
## --------------------------------------------------------
public function sepia2()
{
if ($this->imageResized)
{
$total = imagecolorstotal($this->imageResized);
for ($i = 0; $i < $total; $i++)
{
$index = imagecolorsforindex($this->imageResized, $i);
$red = ($index["red"] * 0.393 + $index["green"] * 0.769 + $index["blue"] * 0.189) / 1.351;
$green = ($index["red"] * 0.349 + $index["green"] * 0.686 + $index["blue"] * 0.168) / 1.203;
$blue = ($index["red"] * 0.272 + $index["green"] * 0.534 + $index["blue"] * 0.131) / 2.140;
imagecolorset($this->imageResized, $i, $red, $green, $blue);
}
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Vintage
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function vintage()
# Alias of gd_filter_monopin
{
$this->gd_filter_vintage();
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Presets By Marc Hibbins
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
/** Apply 'Monopin' preset */
public function gd_filter_monopin()
{
if ($this->imageResized)
{
imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15);
imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
$this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 100);
}
}
## --------------------------------------------------------
public function gd_filter_vintage()
{
if ($this->imageResized)
{
$this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 45);
imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20);
imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35);
imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35);
imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7);
$this->imageResized = $this->gd_apply_overlay($this->imageResized, 'scratch', 10);
}
}
## --------------------------------------------------------
/** Apply a PNG overlay */
private function gd_apply_overlay($im, $type, $amount)
#
# Original Author: Marc Hibbins
# License: Attribution-ShareAlike 3.0
# Purpose:
# Params in:
# Params out:
# Notes:
#
{
$width = imagesx($im);
$height = imagesy($im);
$filter = imagecreatetruecolor($width, $height);
imagealphablending($filter, false);
imagesavealpha($filter, true);
$transparent = imagecolorallocatealpha($filter, 255, 255, 255, 127);
imagefilledrectangle($filter, 0, 0, $width, $height, $transparent);
// *** Resize overlay
$overlay = $this->filterOverlayPath . '/' . $type . '.png';
$png = imagecreatefrompng($overlay);
imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, imagesx($png), imagesy($png));
$comp = imagecreatetruecolor($width, $height);
imagecopy($comp, $im, 0, 0, 0, 0, $width, $height);
imagecopy($comp, $filter, 0, 0, 0, 0, $width, $height);
imagecopymerge($im, $comp, 0, 0, 0, 0, $width, $height, $amount);
imagedestroy($comp);
return $im;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Colorise
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function image_colorize($rgb)
{
imageTrueColorToPalette($this->imageResized, true, 256);
$numColors = imageColorsTotal($this->imageResized);
for ($x = 0; $x < $numColors; $x++)
{
list($r, $g, $b) = array_values(imageColorsForIndex($this->imageResized, $x));
// calculate grayscale in percent
$grayscale = ($r + $g + $b) / 3 / 0xff;
imageColorSet($this->imageResized, $x,
$grayscale * $rgb[0],
$grayscale * $rgb[1],
$grayscale * $rgb[2]
);
}
return true;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Reflection
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = false, $bgColor = '#fff', $stretch = false, $divider = 0)
{
// *** Convert color
$rgbArray = $this->formatColor($bgColor);
$r = $rgbArray['r'];
$g = $rgbArray['g'];
$b = $rgbArray['b'];
$im = $this->imageResized;
$li = imagecreatetruecolor($this->width, 1);
$bgc = imagecolorallocate($li, $r, $g, $b);
imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc);
$bg = imagecreatetruecolor($this->width, $reflectionHeight);
$wh = imagecolorallocate($im, 255, 255, 255);
$im = imagerotate($im, -180, $wh);
imagecopyresampled($bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
$im = $bg;
$bg = imagecreatetruecolor($this->width, $reflectionHeight);
for ($x = 0; $x < $this->width; $x++)
{
imagecopy($bg, $im, $x, 0, $this->width - $x - 1, 0, 1, $reflectionHeight);
}
$im = $bg;
$transaprencyAmount = $this->invertTransparency($startingTransparency, 100);
// *** Fade
if ($stretch)
{
$step = 100 / ($reflectionHeight + $startingTransparency);
}
else
{
$step = 100 / $reflectionHeight;
}
for ($i = 0; $i <= $reflectionHeight; $i++)
{
if ($startingTransparency > 100)
{
$startingTransparency = 100;
}
if ($startingTransparency < 1)
{
$startingTransparency = 1;
}
imagecopymerge($bg, $li, 0, $i, 0, 0, $this->width, 1, $startingTransparency);
$startingTransparency += $step;
}
// *** Apply fade
imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); // Divider
// *** width, height of reflection.
$x = imagesx($im);
$y = imagesy($im);
// *** Determines if the reflection should be displayed inside or outside the image
if ($inside)
{
// Create new blank image with sizes.
$final = imagecreatetruecolor($this->width, $this->height);
imagecopymerge($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100);
imagecopymerge($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100);
}
else
{
// Create new blank image with sizes.
$final = imagecreatetruecolor($this->width, $this->height + $y);
imagecopymerge($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100);
imagecopymerge($final, $im, 0, $this->height, 0, 0, $x, $y, 100);
}
$this->imageResized = $final;
imagedestroy($li);
imagedestroy($im);
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Rotate
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function rotate($value = 90, $bgColor = 'transparent')
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Rotate image
# Param in: (mixed) $degrees: (int) number of degress to rotate image
# (str) param "left": rotate left
# (str) param "right": rotate right
# (str) param "upside": upside-down image
# Param out:
# Reference:
# Notes: The default direction of imageRotate() is counter clockwise.
#
{
if ($this->imageResized)
{
if (is_integer($value))
{
$degrees = $value;
}
// *** Convert color
$rgbArray = $this->formatColor($bgColor);
$r = $rgbArray['r'];
$g = $rgbArray['g'];
$b = $rgbArray['b'];
if (isset($rgbArray['a']))
{
$a = $rgbArray['a'];
}
if (is_string($value))
{
$value = fix_strtolower($value);
switch ($value)
{
case 'left':
$degrees = 90;
break;
case 'right':
$degrees = 270;
break;
case 'upside':
$degrees = 180;
break;
default:
break;
}
}
// *** The default direction of imageRotate() is counter clockwise
// * This makes it clockwise
$degrees = 360 - $degrees;
// *** Create background color
$bg = ImageColorAllocateAlpha($this->imageResized, $r, $g, $b, $a);
// *** Fill with background
ImageFill($this->imageResized, 0, 0, $bg);
// *** Rotate
$this->imageResized = imagerotate($this->imageResized, $degrees, $bg); // Rotate 45 degrees and allocated the transparent colour as the one to make transparent (obviously)
// Ensure alpha transparency
ImageSaveAlpha($this->imageResized, true);
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Round corners
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function roundCorners($radius = 5, $bgColor = 'transparent')
# Author: Jarrod Oberto
# Date: 19-05-2011
# Purpose: Create rounded corners on your image
# Param in: (int) radius = the amount of curvature
# (mixed) $bgColor = the corner background color
# Param out: n/a
# Reference:
# Notes:
#
{
// *** Check if the user wants transparency
$isTransparent = false;
if ( ! is_array($bgColor))
{
if (fix_strtolower($bgColor) == 'transparent')
{
$isTransparent = true;
}
}
// *** If we use transparency, we need to color our curved mask with a unique color
if ($isTransparent)
{
$bgColor = $this->findUnusedGreen();
}
// *** Convert color
$rgbArray = $this->formatColor($bgColor);
$r = $rgbArray['r'];
$g = $rgbArray['g'];
$b = $rgbArray['b'];
if (isset($rgbArray['a']))
{
$a = $rgbArray['a'];
}
// *** Create top-left corner mask (square)
$cornerImg = imagecreatetruecolor($radius, $radius);
//$cornerImg = imagecreate($radius, $radius);
//imagealphablending($cornerImg, true);
//imagesavealpha($cornerImg, true);
//imagealphablending($this->imageResized, false);
//imagesavealpha($this->imageResized, true);
// *** Give it a color
$maskColor = imagecolorallocate($cornerImg, 0, 0, 0);
// *** Replace the mask color (black) to transparent
imagecolortransparent($cornerImg, $maskColor);
// *** Create the image background color
$imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b);
// *** Fill the corner area to the user defined color
imagefill($cornerImg, 0, 0, $imagebgColor);
imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor);
// *** Map to top left corner
imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl
// *** Map rounded corner to other corners by rotating and applying the mask
$cornerImg = imagerotate($cornerImg, 90, 0);
imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl
$cornerImg = imagerotate($cornerImg, 90, 0);
imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br
$cornerImg = imagerotate($cornerImg, 90, 0);
imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr
// *** If corners are to be transparent, we fill our chromakey color as transparent.
if ($isTransparent)
{
//imagecolortransparent($this->imageResized, $imagebgColor);
$this->imageResized = $this->transparentImage($this->imageResized);
imagesavealpha($this->imageResized, true);
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Shadow
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function addShadow($shadowAngle = 45, $blur = 15, $bgColor = 'transparent')
#
# Author: Jarrod Oberto (Adapted from Pascal Naidon)
# Ref: http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en
# Purpose: Add a drop shadow to your image
# Params in: (int) $angle: the angle of the shadow
# (int) $blur: the blur distance
# (mixed) $bgColor: the color of the background
# Params out:
# Notes:
#
{
// *** A higher number results in a smoother shadow
define('STEPS', $blur * 2);
// *** Set the shadow distance
$shadowDistance = $blur * 0.25;
// *** Set blur width and height
$blurWidth = $blurHeight = $blur;
if ($shadowAngle == 0)
{
$distWidth = 0;
$distHeight = 0;
}
else
{
$distWidth = $shadowDistance * cos(deg2rad($shadowAngle));
$distHeight = $shadowDistance * sin(deg2rad($shadowAngle));
}
// *** Convert color
if (fix_strtolower($bgColor) != 'transparent')
{
$rgbArray = $this->formatColor($bgColor);
$r0 = $rgbArray['r'];
$g0 = $rgbArray['g'];
$b0 = $rgbArray['b'];
}
$image = $this->imageResized;
$width = $this->width;
$height = $this->height;
$newImage = imagecreatetruecolor($width, $height);
imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
// *** RGB
$rgb = imagecreatetruecolor($width + $blurWidth, $height + $blurHeight);
$colour = imagecolorallocate($rgb, 0, 0, 0);
imagefilledrectangle($rgb, 0, 0, $width + $blurWidth, $height + $blurHeight, $colour);
$colour = imagecolorallocate($rgb, 255, 255, 255);
//imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
imagefilledrectangle($rgb, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, $width + $blurWidth * 0.5 - $distWidth, $height + $blurWidth * 0.5 - $distHeight, $colour);
//imagecopymerge($rgb, $newImage, 1+$blurWidth*0.5-$distWidth, 1+$blurHeight*0.5-$distHeight, 0,0, $width, $height, 100);
imagecopymerge($rgb, $newImage, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, 0, 0, $width + $blurWidth, $height + $blurHeight, 100);
// *** Shadow (alpha)
$shadow = imagecreatetruecolor($width + $blurWidth, $height + $blurHeight);
imagealphablending($shadow, false);
$colour = imagecolorallocate($shadow, 0, 0, 0);
imagefilledrectangle($shadow, 0, 0, $width + $blurWidth, $height + $blurHeight, $colour);
for ($i = 0; $i <= STEPS; $i++)
{
$t = ((1.0 * $i) / STEPS);
$intensity = 255 * $t * $t;
$colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
$points = array(
$blurWidth * $t, $blurHeight, // Point 1 (x, y)
$blurWidth, $blurHeight * $t, // Point 2 (x, y)
$width, $blurHeight * $t, // Point 3 (x, y)
$width + $blurWidth * (1 - $t), $blurHeight, // Point 4 (x, y)
$width + $blurWidth * (1 - $t), $height, // Point 5 (x, y)
$width, $height + $blurHeight * (1 - $t), // Point 6 (x, y)
$blurWidth, $height + $blurHeight * (1 - $t), // Point 7 (x, y)
$blurWidth * $t, $height // Point 8 (x, y)
);
imagepolygon($shadow, $points, 8, $colour);
}
for ($i = 0; $i <= STEPS; $i++)
{
$t = ((1.0 * $i) / STEPS);
$intensity = 255 * $t * $t;
$colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
imagefilledarc($shadow, $blurWidth - 1, $blurHeight - 1, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 180, 268, $colour, IMG_ARC_PIE);
imagefilledarc($shadow, $width, $blurHeight - 1, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 270, 358, $colour, IMG_ARC_PIE);
imagefilledarc($shadow, $width, $height, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 0, 90, $colour, IMG_ARC_PIE);
imagefilledarc($shadow, $blurWidth - 1, $height, 2 * (1 - $t) * $blurWidth, 2 * (1 - $t) * $blurHeight, 90, 180, $colour, IMG_ARC_PIE);
}
$colour = imagecolorallocate($shadow, 255, 255, 255);
imagefilledrectangle($shadow, $blurWidth, $blurHeight, $width, $height, $colour);
imagefilledrectangle($shadow, $blurWidth * 0.5 - $distWidth, $blurHeight * 0.5 - $distHeight, $width + $blurWidth * 0.5 - 1 - $distWidth, $height + $blurHeight * 0.5 - 1 - $distHeight, $colour);
// *** The magic
imagealphablending($rgb, false);
for ($theX = 0; $theX < imagesx($rgb); $theX++)
{
for ($theY = 0; $theY < imagesy($rgb); $theY++)
{
// *** Get the RGB values for every pixel of the RGB image
$colArray = imagecolorat($rgb, $theX, $theY);
$r = ($colArray >> 16) & 0xFF;
$g = ($colArray >> 8) & 0xFF;
$b = $colArray & 0xFF;
// *** Get the alpha value for every pixel of the shadow image
$colArray = imagecolorat($shadow, $theX, $theY);
$a = $colArray & 0xFF;
$a = 127 - floor($a / 2);
$t = $a / 128.0;
// *** Create color
if (fix_strtolower($bgColor) == 'transparent')
{
$myColour = imagecolorallocatealpha($rgb, $r, $g, $b, $a);
}
else
{
$myColour = imagecolorallocate($rgb, $r * (1.0 - $t) + $r0 * $t, $g * (1.0 - $t) + $g0 * $t, $b * (1.0 - $t) + $b0 * $t);
}
// *** Add color to new rgb image
imagesetpixel($rgb, $theX, $theY, $myColour);
}
}
imagealphablending($rgb, true);
imagesavealpha($rgb, true);
$this->imageResized = $rgb;
imagedestroy($image);
imagedestroy($newImage);
imagedestroy($shadow);
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Add Caption Box
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function addCaptionBox($side = 'b', $thickness = 50, $padding = 0, $bgColor = '#000', $transaprencyAmount = 30)
#
# Author: Jarrod Oberto
# Date: 26 May 2011
# Purpose: Add a caption box
# Params in: (str) $side: the side to add the caption box (t, r, b, or l).
# (int) $thickness: how thick you want the caption box to be.
# (mixed) $bgColor: The color of the caption box.
# (int) $transaprencyAmount: The amount of transparency to be
# applied.
# Params out: n/a
# Notes:
#
{
$side = fix_strtolower($side);
// *** Convert color
$rgbArray = $this->formatColor($bgColor);
$r = $rgbArray['r'];
$g = $rgbArray['g'];
$b = $rgbArray['b'];
$positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding);
// *** Store incase we want to use method addTextToCaptionBox()
$this->captionBoxPositionArray = $positionArray;
$transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, false);
$transparent = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount);
imagefilledrectangle($this->imageResized, $positionArray['x1'], $positionArray['y1'], $positionArray['x2'], $positionArray['y2'], $transparent);
}
## --------------------------------------------------------
public function addTextToCaptionBox($text, $fontColor = '#fff', $fontSize = 12, $angle = 0, $font = null)
#
# Author: Jarrod Oberto
# Date: 03 Aug 11
# Purpose: Simplify adding text to a caption box by automatically
# locating the center of the caption box
# Params in: The usually text paams (less a couple)
# Params out: n/a
# Notes:
#
{
// *** Get the caption box measurements
if (count($this->captionBoxPositionArray) == 4)
{
$x1 = $this->captionBoxPositionArray['x1'];
$x2 = $this->captionBoxPositionArray['x2'];
$y1 = $this->captionBoxPositionArray['y1'];
$y2 = $this->captionBoxPositionArray['y2'];
}
else
{
if ($this->debug)
{
throw new Exception('No caption box found.');
}
else
{
return false;
}
}
// *** Get text font
$font = $this->getTextFont($font);
// *** Get text size
$textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
$textWidth = $textSizeArray['width'];
$textHeight = $textSizeArray['height'];
// *** Find the width/height middle points
$boxXMiddle = (($x2 - $x1) / 2);
$boxYMiddle = (($y2 - $y1) / 2);
// *** Box middle - half the text width/height
$xPos = ($x1 + $boxXMiddle) - ($textWidth / 2);
$yPos = ($y1 + $boxYMiddle) - ($textHeight / 2);
$pos = $xPos . 'x' . $yPos;
$this->addText($text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font);
}
## --------------------------------------------------------
private function calculateCaptionBoxPosition($side, $thickness, $padding)
{
$positionArray = array();
switch ($side)
{
case 't':
$positionArray['x1'] = 0;
$positionArray['y1'] = $padding;
$positionArray['x2'] = $this->width;
$positionArray['y2'] = $thickness + $padding;
break;
case 'r':
$positionArray['x1'] = $this->width - $thickness - $padding;
$positionArray['y1'] = 0;
$positionArray['x2'] = $this->width - $padding;
$positionArray['y2'] = $this->height;
break;
case 'b':
$positionArray['x1'] = 0;
$positionArray['y1'] = $this->height - $thickness - $padding;
$positionArray['x2'] = $this->width;
$positionArray['y2'] = $this->height - $padding;
break;
case 'l':
$positionArray['x1'] = $padding;
$positionArray['y1'] = 0;
$positionArray['x2'] = $thickness + $padding;
$positionArray['y2'] = $this->height;
break;
default:
break;
}
return $positionArray;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Get EXIF Data
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function getExif($debug = false)
# Author: Jarrod Oberto
# Date: 07-05-2011
# Purpose: Get image EXIF data
# Param in: n/a
# Param out: An associate array of EXIF data
# Reference:
# Notes:
# 23 May 13 : added orientation flag -jco
#
{
if ( ! $this->debug || ! $debug)
{
$debug = false;
}
// *** Check all is good - check the EXIF library exists and the file exists, too.
if ( ! $this->testEXIFInstalled())
{
if ($debug)
{
throw new Exception('The EXIF Library is not installed.');
}
else
{
return array();
}
};
if ( ! file_exists($this->fileName))
{
if ($debug)
{
throw new Exception('Image not found.');
}
else
{
return array();
}
};
if ($this->fileExtension != '.jpg')
{
if ($debug)
{
throw new Exception('Metadata not supported for this image type.');
}
else
{
return array();
}
};
$exifData = exif_read_data($this->fileName, 'IFD0');
// *** Format the apperture value
$ev = $exifData['ApertureValue'];
$apPeicesArray = explode('/', $ev);
if (count($apPeicesArray) == 2)
{
$apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . ' EV';
}
else
{
$apertureValue = '';
}
// *** Format the focal length
$focalLength = $exifData['FocalLength'];
$flPeicesArray = explode('/', $focalLength);
if (count($flPeicesArray) == 2)
{
$focalLength = $flPeicesArray[0] / $flPeicesArray[1] . '.0 mm';
}
else
{
$focalLength = '';
}
// *** Format fNumber
$fNumber = $exifData['FNumber'];
$fnPeicesArray = explode('/', $fNumber);
if (count($fnPeicesArray) == 2)
{
$fNumber = $fnPeicesArray[0] / $fnPeicesArray[1];
}
else
{
$fNumber = '';
}
// *** Resolve ExposureProgram
if (isset($exifData['ExposureProgram']))
{
$ep = $exifData['ExposureProgram'];
}
if (isset($ep))
{
$ep = $this->resolveExposureProgram($ep);
}
// *** Resolve MeteringMode
$mm = $exifData['MeteringMode'];
$mm = $this->resolveMeteringMode($mm);
// *** Resolve Flash
$flash = $exifData['Flash'];
$flash = $this->resolveFlash($flash);
if (isset($exifData['Make']))
{
$exifDataArray['make'] = $exifData['Make'];
}
else
{
$exifDataArray['make'] = '';
}
if (isset($exifData['Model']))
{
$exifDataArray['model'] = $exifData['Model'];
}
else
{
$exifDataArray['model'] = '';
}
if (isset($exifData['DateTime']))
{
$exifDataArray['date'] = $exifData['DateTime'];
}
else
{
$exifDataArray['date'] = '';
}
if (isset($exifData['ExposureTime']))
{
$exifDataArray['exposure time'] = $exifData['ExposureTime'] . ' sec.';
}
else
{
$exifDataArray['exposure time'] = '';
}
if ($apertureValue != '')
{
$exifDataArray['aperture value'] = $apertureValue;
}
else
{
$exifDataArray['aperture value'] = '';
}
if (isset($exifData['COMPUTED']['ApertureFNumber']))
{
$exifDataArray['f-stop'] = $exifData['COMPUTED']['ApertureFNumber'];
}
else
{
$exifDataArray['f-stop'] = '';
}
if (isset($exifData['FNumber']))
{
$exifDataArray['fnumber'] = $exifData['FNumber'];
}
else
{
$exifDataArray['fnumber'] = '';
}
if ($fNumber != '')
{
$exifDataArray['fnumber value'] = $fNumber;
}
else
{
$exifDataArray['fnumber value'] = '';
}
if (isset($exifData['ISOSpeedRatings']))
{
$exifDataArray['iso'] = $exifData['ISOSpeedRatings'];
}
else
{
$exifDataArray['iso'] = '';
}
if ($focalLength != '')
{
$exifDataArray['focal length'] = $focalLength;
}
else
{
$exifDataArray['focal length'] = '';
}
if (isset($ep))
{
$exifDataArray['exposure program'] = $ep;
}
else
{
$exifDataArray['exposure program'] = '';
}
if ($mm != '')
{
$exifDataArray['metering mode'] = $mm;
}
else
{
$exifDataArray['metering mode'] = '';
}
if ($flash != '')
{
$exifDataArray['flash status'] = $flash;
}
else
{
$exifDataArray['flash status'] = '';
}
if (isset($exifData['Artist']))
{
$exifDataArray['creator'] = $exifData['Artist'];
}
else
{
$exifDataArray['creator'] = '';
}
if (isset($exifData['Copyright']))
{
$exifDataArray['copyright'] = $exifData['Copyright'];
}
else
{
$exifDataArray['copyright'] = '';
}
// *** Orientation
if (isset($exifData['Orientation']))
{
$exifDataArray['orientation'] = $exifData['Orientation'];
}
else
{
$exifDataArray['orientation'] = '';
}
return $exifDataArray;
}
## --------------------------------------------------------
private function resolveExposureProgram($ep)
{
switch ($ep)
{
case 0:
$ep = '';
break;
case 1:
$ep = 'manual';
break;
case 2:
$ep = 'normal program';
break;
case 3:
$ep = 'aperture priority';
break;
case 4:
$ep = 'shutter priority';
break;
case 5:
$ep = 'creative program';
break;
case 6:
$ep = 'action program';
break;
case 7:
$ep = 'portrait mode';
break;
case 8:
$ep = 'landscape mode';
break;
default:
break;
}
return $ep;
}
## --------------------------------------------------------
private function resolveMeteringMode($mm)
{
switch ($mm)
{
case 0:
$mm = 'unknown';
break;
case 1:
$mm = 'average';
break;
case 2:
$mm = 'center weighted average';
break;
case 3:
$mm = 'spot';
break;
case 4:
$mm = 'multi spot';
break;
case 5:
$mm = 'pattern';
break;
case 6:
$mm = 'partial';
break;
case 255:
$mm = 'other';
break;
default:
break;
}
return $mm;
}
## --------------------------------------------------------
private function resolveFlash($flash)
{
switch ($flash)
{
case 0:
$flash = 'flash did not fire';
break;
case 1:
$flash = 'flash fired';
break;
case 5:
$flash = 'strobe return light not detected';
break;
case 7:
$flash = 'strobe return light detected';
break;
case 9:
$flash = 'flash fired, compulsory flash mode';
break;
case 13:
$flash = 'flash fired, compulsory flash mode, return light not detected';
break;
case 15:
$flash = 'flash fired, compulsory flash mode, return light detected';
break;
case 16:
$flash = 'flash did not fire, compulsory flash mode';
break;
case 24:
$flash = 'flash did not fire, auto mode';
break;
case 25:
$flash = 'flash fired, auto mode';
break;
case 29:
$flash = 'flash fired, auto mode, return light not detected';
break;
case 31:
$flash = 'flash fired, auto mode, return light detected';
break;
case 32:
$flash = 'no flash function';
break;
case 65:
$flash = 'flash fired, red-eye reduction mode';
break;
case 69:
$flash = 'flash fired, red-eye reduction mode, return light not detected';
break;
case 71:
$flash = 'flash fired, red-eye reduction mode, return light detected';
break;
case 73:
$flash = 'flash fired, compulsory flash mode, red-eye reduction mode';
break;
case 77:
$flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
break;
case 79:
$flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
break;
case 89:
$flash = 'flash fired, auto mode, red-eye reduction mode';
break;
case 93:
$flash = 'flash fired, auto mode, return light not detected, red-eye reduction mode';
break;
case 95:
$flash = 'flash fired, auto mode, return light detected, red-eye reduction mode';
break;
default:
break;
}
return $flash;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Get IPTC Data
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Write IPTC Data
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function writeIPTCcaption($value)
# Caption
{
$this->writeIPTC(120, $value);
}
## --------------------------------------------------------
public function writeIPTCwriter($value)
{
//$this->writeIPTC(65, $value);
}
## --------------------------------------------------------
private function writeIPTC($dat, $value)
{
# LIMIT TO JPG
$caption_block = $this->iptc_maketag(2, $dat, $value);
$image_string = iptcembed($caption_block, $this->fileName);
file_put_contents('iptc.jpg', $image_string);
}
## --------------------------------------------------------
private function iptc_maketag($rec, $dat, $val)
# Author: Thies C. Arntzen
# Purpose: Function to format the new IPTC text
# Param in: $rec: Application record. (Were working with #2)
# $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM
# specification:
# http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
# $val: Value/data/text. Make sure this is within the length
# constraints of the IPTC IIM specification
# Ref: http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/
# http://php.net/manual/en/function.iptcembed.php
#
{
$len = strlen($val);
if ($len < 0x8000)
{
return chr(0x1c) . chr($rec) . chr($dat) .
chr($len >> 8) .
chr($len & 0xff) .
$val;
}
else
{
return chr(0x1c) . chr($rec) . chr($dat) .
chr(0x80) . chr(0x04) .
chr(($len >> 24) & 0xff) .
chr(($len >> 16) & 0xff) .
chr(($len >> 8) & 0xff) .
chr(($len) & 0xff) .
$val;
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Write XMP Data
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
//http://xmpphptoolkit.sourceforge.net/
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Add Text
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function addText($text, $pos = '20x20', $padding = 0, $fontColor = '#fff', $fontSize = 12, $angle = 0, $font = null)
# Author: Jarrod Oberto
# Date: 18-11-09
# Purpose: Add text to an image
# Param in:
# Param out:
# Reference: http://php.net/manual/en/function.imagettftext.php
# Notes: Make sure you supply the font.
#
{
// *** Convert color
$rgbArray = $this->formatColor($fontColor);
$r = $rgbArray['r'];
$g = $rgbArray['g'];
$b = $rgbArray['b'];
// *** Get text font
$font = $this->getTextFont($font);
// *** Get text size
$textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
$textWidth = $textSizeArray['width'];
$textHeight = $textSizeArray['height'];
// *** Find co-ords to place text
$posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, false);
$x = $posArray['width'];
$y = $posArray['height'];
$fontColor = imagecolorallocate($this->imageResized, $r, $g, $b);
// *** Add text
imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, $text);
}
## --------------------------------------------------------
private function getTextFont($font)
{
// *** Font path (shou
$fontPath = dirname(__FILE__) . '/' . $this->fontDir;
// *** The below is/may be needed depending on your version (see ref)
putenv('GDFONTPATH=' . realpath('.'));
// *** Check if the passed in font exsits...
if ($font == null || ! file_exists($font))
{
// *** ...If not, default to this font.
$font = $fontPath . '/arimo.ttf';
// *** Check our default font exists...
if ( ! file_exists($font))
{
// *** If not, return false
if ($this->debug)
{
throw new Exception('Font not found');
}
else
{
return false;
}
}
}
return $font;
}
## --------------------------------------------------------
private function getTextSize($fontSize, $angle, $font, $text)
{
// *** Define box (so we can get the width)
$box = @imageTTFBbox($fontSize, $angle, $font, $text);
// *** Get width of text from dimensions
$textWidth = abs($box[4] - $box[0]);
// *** Get height of text from dimensions (should also be same as $fontSize)
$textHeight = abs($box[5] - $box[1]);
return array( 'height' => $textHeight, 'width' => $textWidth );
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
Add Watermark
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0)
# Author: Jarrod Oberto
# Date: 18-11-09
# Purpose: Add watermark image
# Param in: (str) $watermark: The watermark image
# (str) $pos: Could be a pre-determined position such as:
# tl = top left,
# t = top (middle),
# tr = top right,
# l = left,
# m = middle,
# r = right,
# bl = bottom left,
# b = bottom (middle),
# br = bottom right
# Or, it could be a co-ordinate position such as: 50x100
#
# (int) $padding: If using a pre-determined position you can
# adjust the padding from the edges by passing an amount
# in pixels. If using co-ordinates, this value is ignored.
# Param out:
# Reference: http://www.php.net/manual/en/image.examples-watermark.php
# Notes: Based on example in reference.
#
#
{
// Load the stamp and the photo to apply the watermark to
$stamp = $this->openImage($watermarkImage); # stamp
$im = $this->imageResized; # photo
// *** Get stamps width and height
$sx = imagesx($stamp);
$sy = imagesy($stamp);
// *** Find co-ords to place image
$posArray = $this->calculatePosition($pos, $padding, $sx, $sy);
$x = $posArray['width'];
$y = $posArray['height'];
// *** Set watermark opacity
if (fix_strtolower(strrchr($watermarkImage, '.')) == '.png')
{
$opacity = $this->invertTransparency($opacity, 100);
$this->filterOpacity($stamp, $opacity);
}
// Copy the watermark image onto our photo
imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp));
}
## --------------------------------------------------------
private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = true)
#
# Author: Jarrod Oberto
# Date: 08-05-11
# Purpose: Calculate the x, y pixel cordinates of the asset to place
# Params in: (str) $pos: Either something like: "tl", "l", "br" or an
# exact position like: "100x50"
# (int) $padding: The amount of padding from the edge. Only
# used for the predefined $pos.
# (int) $assetWidth: The width of the asset to add to the image
# (int) $assetHeight: The height of the asset to add to the image
# (bol) $upperLeft: if true, the asset will be positioned based
# on the upper left x, y coords. If false, it means you're
# using the lower left as the basepoint and this will
# convert it to the upper left position
# Params out:
# NOTE: this is done from the UPPER left corner!! But will convert lower
# left basepoints to upper left if $upperleft is set to false
#
#
{
$pos = fix_strtolower($pos);
// *** If co-ords have been entered
if (strstr($pos, 'x'))
{
$pos = str_replace(' ', '', $pos);
$xyArray = explode('x', $pos);
list($width, $height) = $xyArray;
}
else
{
switch ($pos)
{
case 'tl':
$width = 0 + $padding;
$height = 0 + $padding;
break;
case 't':
$width = ($this->width / 2) - ($assetWidth / 2);
$height = 0 + $padding;
break;
case 'tr':
$width = $this->width - $assetWidth - $padding;
$height = 0 + $padding;;
break;
case 'l':
$width = 0 + $padding;
$height = ($this->height / 2) - ($assetHeight / 2);
break;
case 'm':
$width = ($this->width / 2) - ($assetWidth / 2);
$height = ($this->height / 2) - ($assetHeight / 2);
break;
case 'r':
$width = $this->width - $assetWidth - $padding;
$height = ($this->height / 2) - ($assetHeight / 2);
break;
case 'bl':
$width = 0 + $padding;
$height = $this->height - $assetHeight - $padding;
break;
case 'b':
$width = ($this->width / 2) - ($assetWidth / 2);
$height = $this->height - $assetHeight - $padding;
break;
case 'br':
$width = $this->width - $assetWidth - $padding;
$height = $this->height - $assetHeight - $padding;
break;
default:
$width = 0;
$height = 0;
break;
}
}
if ( ! $upperLeft)
{
$height = $height + $assetHeight;
}
return array( 'width' => $width, 'height' => $height );
}
## --------------------------------------------------------
private function filterOpacity(&$img, $opacity = 75)
#
# Author: aiden dot mail at freemail dot hu
# Author date: 29-03-08 08:16
# Date added: 08-05-11
# Purpose: Change opacity of image
# Params in: $img: Image resource id
# (int) $opacity: the opacity amount: 0-100, 100 being not opaque.
# Params out: (bool) true on success, else false
# Ref: http://www.php.net/manual/en/function.imagefilter.php#82162
# Notes: png only
#
{
if ( ! isset($opacity))
{
return false;
}
if ($opacity == 100)
{
return true;
}
$opacity /= 100;
//get image width and height
$w = imagesx($img);
$h = imagesy($img);
//turn alpha blending off
imagealphablending($img, false);
//find the most opaque pixel in the image (the one with the smallest alpha value)
$minalpha = 127;
for ($x = 0; $x < $w; $x++)
{
for ($y = 0; $y < $h; $y++)
{
$alpha = (imagecolorat($img, $x, $y) >> 24) & 0xFF;
if ($alpha < $minalpha)
{
$minalpha = $alpha;
}
}
}