2    # ========================================================================# 
    4    #  This work is licensed under the Creative Commons Attribution 3.0 Unported 
    5    #  License. To view a copy of this license, 
    6    #  visit http://creativecommons.org/licenses/by/3.0/ or send a letter to 
    7    #  Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 
   10    #  All rights reserved. 
   12    #  Author:    Jarrod Oberto 
   15    #  Purpose:   Provide tools for image manipulation using GD 
   16    #  Param In:  See functions. 
   17    #  Param Out: Produces a resized image 
   18    #  Requires : Requires PHP GD library. 
   20    #                     include("lib/php_image_magician.php"); 
   21    #                     $magicianObj = new resize('images/car.jpg'); 
   22    #                     $magicianObj -> resizeImage(150, 100, 0); 
   23    #                     $magicianObj -> saveImage('images/car_small.jpg', 100); 
   25    #        - See end of doc for more examples - 
   27    #  Supported file types include: jpg, png, gif, bmp, psd (read) 
   31    #  The following functions are taken from phpThumb() [available from 
   32    #    http://phpthumb.sourceforge.net], and are used with written permission 
   33    #  from James Heinrich. 
   36    #      - LittleEndian2String 
   38    #  The following functions are from Marc Hibbins and are used with written 
   39    #  permission (are also under the Attribution-ShareAlike 
   40    #  [http://creativecommons.org/licenses/by-sa/3.0/] license. 
   43    #  PhpPsdReader is used with written permission from Tim de Koning. 
   44    #  [http://www.kingsquare.nl/phppsdreader] 
   48    #  Modificatoin history 
   49    #  Date      Initials  Ver Description 
   50    #  10-05-11  J.C.O   0.0 Initial build 
   51    #  01-06-11  J.C.O   0.1.1   * Added reflections 
   52    #              * Added Rounded corners 
   53    #              * You can now use PNG interlacing 
   56    #              * Added vintage filter 
   57    #              * Added dynamic image resizing (resize on the fly) 
   59    #  05-06-11  J.C.O   0.1.1.1 * Fixed undefined variables 
   60    #  17-06-11  J.C.O   0.1.2   * Added image_batch_class.php class 
   62    #  26-07-11  J.C.O   0.1.4 * Added support for external images 
   63    #              * Can now set the crop poisition 
   64    #  03-08-11  J.C.O   0.1.5 * Added reset() method to reset resource to 
   65    #                original input file. 
   66    #              * Added method addTextToCaptionBox() to 
   67    #                simplify adding text to a caption box. 
   68    #              * Added experimental writeIPTC. (not finished) 
   69    #              * Added experimental readIPTC. (not finished) 
   70    #  11-08-11  J.C.O     * Added initial border presets. 
   71    #  30-08-11  J.C.O     * Added 'auto' crop option to crop portrait 
   72    #                images near the top. 
   73    #  08-09-11  J.C.O     * Added cropImage() method to allow standalone 
   75    #  17-09-11  J.C.O     * Added setCropFromTop() set method - set the 
   76    #                percentage to crop from the top when using 
   78    #              * Added setTransparency() set method - allows you 
   79    #                to turn transparency off (like when saving 
   81    #              * Added setFillColor() set method - set the 
   82    #                background color to use instead of transparency. 
   83    #  05-11-11  J.C.O   0.1.5.1 * Fixed interlacing option 
   86    #  Known issues & Limitations: 
   87    # ------------------------------- 
   88    #  Not so much an issue, the image is destroyed on the deconstruct rather than 
   89    #  when we have finished with it. The reason for this is that we don't know 
   90    #  when we're finished with it as you can both save the image and display 
   91    #  it directly to the screen (imagedestroy($this->imageResized)) 
   93    #  Opening BMP files is slow. A test with 884 bmp files processed in a loop 
   94    #  takes forever - over 5 min. This test inlcuded opening the file, then 
   95    #  getting and displaying its width and height. 
   98    # ------------------------------- 
  100    #  $forceStretch can be disabled by calling method setForceStretch with false 
  101    #  parameter. If disabled, if an images original size is smaller than the size 
  102    #  specified by the user, the original size will be used. This is useful when 
  103    #  dealing with small images. 
  105    #  If enabled, images smaller than the size specified will be stretched to 
  109    # ------------------------------- 
  110    #  * If you're resizing a transparent png and saving it as a jpg, set 
  111    #  $keepTransparency to false with: $magicianObj->setTransparency(false); 
  115    #    * BMP SUPPORT (read & write) 
  116    #    * PSD (photoshop) support (read) 
  118    #      - Preserve transparency (png, gif) 
  119    #      - Apply sharpening (jpg) (requires PHP >= 5.1.0) 
  120    #      - Set image quality (jpg, png) 
  123    #        - resize by width (auto height) 
  124    #        - resize by height (auto width) 
  125    #        - auto (automatically determine the best of the above modes to use) 
  126    #        - crop - resize as best as it can then crop the rest 
  127    #      - Force stretching of smaller images (upscale) 
  129    #      - Convert to grey scale 
  130    #      - Convert to black and white 
  132    #      - Convert to negative 
  134    #      - Rotate using predefined "left", "right", or "180"; or any custom degree amount 
  135    #    * EXTRACT EXIF DATA (requires exif module) 
  150    #      - Specify exact x, y placement 
  151    #      - Or, specify using one of the 9 pre-defined placements such as "tl" 
  152    #        (for top left), "m" (for middle), "br" (for bottom right) 
  153    #        - also specify padding from edge amount (optional). 
  154    #      - Set opacity of watermark (png). 
  156    #    * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff) 
  157    #    * SAVE IMAGE OR OUTPUT TO SCREEN 
  160    # ========================================================================# 
  171     private $width;         # Current width (width after resize)
 
  200 ## -------------------------------------------------------- 
  203     # Author:     Jarrod Oberto 
  205     # Purpose:    Constructor 
  206     # Param in:   $fileName: File name and path. 
  212     if (!$this->testGDInstalled()) { 
if ($this->debug) { 
throw new Exception(
'The GD Library is not installed.'); }
else{ 
throw new Exception(); }};
 
  221         $this->image = $this->openImage(
$fileName);
 
  228         if ($this->testIsImage($this->image))
 
  231             $this->width  = imagesx($this->image);
 
  232             $this->widthOriginal = imagesx($this->image);
 
  233             $this->height = imagesy($this->image);
 
  234             $this->heightOriginal = imagesy($this->image);
 
  246             $this->imageSize = getimagesize($this->fileName);
 
  249       $this->errorArray[] = 
'File is not an image';
 
  253 ## -------------------------------------------------------- 
  257     $this->psdReaderPath = __DIR__ . 
'/classPhpPsdReader.php';
 
  258     $this->filterOverlayPath = __DIR__ . 
'/filters';
 
  261     $this->isInterlace = 
false;
 
  271     public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = 
false, $autoRotate = 
false)
 
  272     # Author:     Jarrod Oberto 
  274     # Purpose:    Resizes the image 
  275     # Param in:   $newWidth: 
  277     #             $option:     0 / exact = defined size; 
  278     #                          1 / portrait = keep aspect set height; 
  279     #                          2 / landscape = keep aspect set width; 
  281   #                          4 / crop= resize and crop; 
  283   #         $option can also be an array containing options for 
  284   #         cropping. E.G., array('crop', 'r') 
  286   #         This array only applies to 'crop' and the 'r' refers to 
  287   #         "crop right". Other value include; tl, t, tr, l, m (default), 
  288   #         r, bl, b, br, or you can specify your own co-ords (which 
  291   #       $sharpen:    true: sharpen (jpg only); 
  292   #                false: don't sharpen 
  295     # Notes:      To clarify the $option input: 
  296     #               0 = The exact height and width dimensions you set. 
  297     #               1 = Whatever height is passed in will be the height that 
  298     #                   is set. The width will be calculated and set automatically 
  299     #                   to a the value that keeps the original aspect ratio. 
  300     #               2 = The same but based on the width. We try make the image the 
  301   #                  biggest size we can while stil fitting inside the box size 
  302     #               3 = Depending whether the image is landscape or portrait, this 
  303     #                   will automatically determine whether to resize via 
  305   #               4 = Will resize and then crop the image for best fit 
  307   #       forceStretch can be applied to options 1,2,3 and 4 
  315     } 
else if (strpos($option, 
'-') !== 
false) {
 
  317       $optionPiecesArray = explode(
'-', $option);
 
  318       $cropPos = end($optionPiecesArray);
 
  322     $option = $this->prepOption($option);
 
  325     if (!$this->image) { 
if ($this->debug) { 
throw new Exception(
'file ' . $this->getFileName() .
' is missing or invalid'); }
else{ 
throw new Exception(); }};
 
  328     $dimensionsArray = $this->
getDimensions($newWidth, $newHeight, $option);
 
  330     $optimalWidth  = $dimensionsArray[
'optimalWidth'];
 
  331     $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  334     $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
 
  335     $this->
keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized);
 
  336     imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
 
  340     if ($option == 4 || $option == 
'crop') {
 
  342       if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight)) {
 
  343         $this->
crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
 
  350       $exifData = $this->getExif(
false);
 
  351       if (count($exifData) > 0) {
 
  353         switch($exifData[
'orientation']) {
 
  355                 $this->imageResized = imagerotate($this->imageResized,90,0);
 
  358                 $this->imageResized = imagerotate($this->imageResized,180,0);
 
  361                 $this->imageResized = imagerotate($this->imageResized,-90,0);
 
  368     if ($sharpen && in_array($this->fileExtension, $this->sharpenArray)) {
 
  375 ## -------------------------------------------------------- 
  377   public function cropImage($newWidth, $newHeight, $cropPos = 
'm')
 
  378     # Author:     Jarrod Oberto 
  380     # Purpose:    Crops the image 
  381     # Param in:   $newWidth: crop with 
  382     #             $newHeight: crop height 
  383   #       $cropPos: Can be any of the following: 
  384   #             tl, t, tr, l, m, r, bl, b, br, auto 
  386   #             a custom position such as '30x50' 
  394     if (!$this->image) { 
if ($this->debug) { 
throw new Exception(
'file ' . $this->getFileName() .
' is missing or invalid'); }
else{ 
throw new Exception(); }};
 
  397     $this->
crop($this->width, $this->height, $newWidth, $newHeight, $cropPos);
 
  401 ## -------------------------------------------------------- 
  404     # Author:     Jarrod Oberto 
  406     # Purpose:    Keep transparency for png and gif image 
  414     if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency) {
 
  415       imagealphablending($im, 
false);
 
  416       imagesavealpha($im, 
true);
 
  417       $transparent = imagecolorallocatealpha($im, 255, 255, 255, 127);
 
  418       imagefilledrectangle($im, 0, 0, 
$width, $height, $transparent);
 
  420       $color = imagecolorallocate($im, $this->fillColorArray[
'r'], $this->fillColorArray[
'g'], $this->fillColorArray[
'b']);
 
  421       imagefilledrectangle($im, 0, 0, 
$width, $height, $color);
 
  425 ## -------------------------------------------------------- 
  427     private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)
 
  428     # Author:     Jarrod Oberto 
  430     # Purpose:    Crops the image 
  431     # Param in:   $newWidth: 
  440     $cropArray = $this->
getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
 
  441     $cropStartX = $cropArray[
'x'];
 
  442     $cropStartY = $cropArray[
'y'];
 
  445     $crop = imagecreatetruecolor($newWidth , $newHeight);
 
  447     imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
 
  449     $this->imageResized = $crop;
 
  452     $this->width = $newWidth;
 
  453     $this->height = $newHeight;
 
  457 ## -------------------------------------------------------- 
  459   private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos=
'm')
 
  461   # Author:   Jarrod Oberto 
  463   # Purpose:  Set the cropping area. 
  465   # Params out: (array) the crop x and y co-ordinates. 
  466   # Notes:    When specifying the exact pixel crop position (eg 10x15), be 
  467   #       very careful as it's easy to crop out of the image leaving 
  474     if (strstr($pos, 
'x')) {
 
  475       $pos = str_replace(
' ', 
'', $pos);
 
  477       $xyArray = explode(
'x', $pos);
 
  478       list($cropStartX, $cropStartY) = $xyArray;
 
  489           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 
  494           $cropStartX = $optimalWidth - $newWidth;
 
  500           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 
  504           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 
  505           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 
  509           $cropStartX = $optimalWidth - $newWidth;
 
  510           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 
  515           $cropStartY = $optimalHeight - $newHeight;
 
  519           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 
  520           $cropStartY = $optimalHeight - $newHeight;
 
  524           $cropStartX = $optimalWidth - $newWidth;
 
  525           $cropStartY = $optimalHeight - $newHeight;
 
  530           if ($optimalHeight > $optimalWidth) {
 
  531             $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 
  532             $cropStartY = ($this->cropFromTopPercent /100) * $optimalHeight;
 
  536             $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 
  537             $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 
  543           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 
  544           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 
  549     return array(
'x' => $cropStartX, 
'y' => $cropStartY);
 
  552 ## -------------------------------------------------------- 
  555     # Author:     Jarrod Oberto 
  557     # Purpose:    Get new image dimensions based on user specificaions 
  558     # Param in:   $newWidth: 
  560     # Param out:  Array of new width and height values 
  562     # Notes:    If $option = 3 then this function is call recursivly 
  564   #       To clarify the $option input: 
  565     #               0 = The exact height and width dimensions you set. 
  566     #               1 = Whatever height is passed in will be the height that 
  567     #                   is set. The width will be calculated and set automatically 
  568     #                   to a the value that keeps the original aspect ratio. 
  569     #               2 = The same but based on the width. 
  570     #               3 = Depending whether the image is landscape or portrait, this 
  571     #                   will automatically determine whether to resize via 
  572     #                   dimension 1,2 or 0. 
  573   #               4 = Resize the image as much as possible, then crop the 
  577         switch (strval($option))
 
  581                 $optimalWidth = $newWidth;
 
  582                 $optimalHeight= $newHeight;
 
  587         $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  588         $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  593         $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  594         $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  598                 $dimensionsArray = $this->
getSizeByAuto($newWidth, $newHeight);
 
  599         $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  600         $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  605         $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  606         $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  610     return array(
'optimalWidth' => $optimalWidth, 
'optimalHeight' => $optimalHeight);
 
  613 ## -------------------------------------------------------- 
  618     if (!$this->forceStretch) {
 
  621       if ($this->height < $newHeight) {
 
  622         return array(
'optimalWidth' => $this->width, 
'optimalHeight' => $this->height);
 
  628         $newWidth = $newHeight * $ratio;
 
  631     return array(
'optimalWidth' => $newWidth, 
'optimalHeight' => $newHeight);
 
  634 ## -------------------------------------------------------- 
  639     if (!$this->forceStretch) {
 
  642       if ($this->width < $newWidth) {
 
  643         return array(
'optimalWidth' => $this->width, 
'optimalHeight' => $this->height);
 
  649         $newHeight = $newWidth * $ratio;
 
  652     return array(
'optimalWidth' => $newWidth, 
'optimalHeight' => $newHeight);
 
  655 ## -------------------------------------------------------- 
  658     # Author:     Jarrod Oberto 
  660     # Purpose:    Depending on the height, choose to resize by 0, 1, or 2 
  661     # Param in:   The new height and new width 
  666     if (!$this->forceStretch) {
 
  669       if ($this->width < $newWidth && $this->height < $newHeight) {
 
  670         return array(
'optimalWidth' => $this->width, 
'optimalHeight' => $this->height);
 
  674         if ($this->height < $this->width)
 
  681       $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  682       $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  684         elseif ($this->height > $this->width)
 
  691       $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  692       $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  698       if ($newHeight < $newWidth) {
 
  702         $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  703         $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  704       } 
else if ($newHeight > $newWidth) {
 
  708         $optimalWidth = $dimensionsArray[
'optimalWidth'];
 
  709         $optimalHeight = $dimensionsArray[
'optimalHeight'];
 
  712         $optimalWidth = $newWidth;
 
  713         $optimalHeight= $newHeight;
 
  717     return array(
'optimalWidth' => $optimalWidth, 
'optimalHeight' => $optimalHeight);
 
  720 ## -------------------------------------------------------- 
  723   # Author:     Jarrod Oberto 
  725     # Purpose:    Get optimal crop dimensions 
  726     # Param in:   width and height as requested by user (fig 3) 
  727     # Param out:  Array of optimal width and height (fig 2) 
  729     # Notes:      The optimal width and height return are not the same as the 
  730   #       same as the width and height passed in. For example: 
  733   #   |-----------------|     |------------|       |-------| 
  734   #   |             |   =>  |**|      |**|   =>  |       | 
  736     #   |           |       |------------|       |-------| 
  737   #   |-----------------| 
  738   #        original                optimal             crop 
  742   #       300 x 250           150 x 125          150 x 100 
  744   #    The optimal size is the smallest size (that is closest to the crop size) 
  745   #    while retaining proportion/ratio. 
  747   #  The crop size is the optimal size that has been cropped on one axis to 
  748   #  make the image the exact size specified by the user. 
  750   #               * represent cropped area 
  755     if (!$this->forceStretch) {
 
  758       if ($this->width < $newWidth && $this->height < $newHeight) {
 
  759         return array(
'optimalWidth' => $this->width, 
'optimalHeight' => $this->height);
 
  763     $heightRatio = $this->height / $newHeight;
 
  764     $widthRatio  = $this->width /  $newWidth;
 
  766     if ($heightRatio < $widthRatio) {
 
  767       $optimalRatio = $heightRatio;
 
  769       $optimalRatio = $widthRatio;
 
  772     $optimalHeight = round( $this->height / $optimalRatio );
 
  773     $optimalWidth  = round( $this->width  / $optimalRatio );
 
  775     return array(
'optimalWidth' => $optimalWidth, 
'optimalHeight' => $optimalHeight);
 
  778 ## -------------------------------------------------------- 
  781     # Author:     Jarrod Oberto 
  783     # Purpose:    Sharpen image 
  788     # Credit:   Incorporates Joe Lencioni (August 6, 2008) code 
  791     if (version_compare(PHP_VERSION, 
'5.1.0') >= 0) {
 
  794       if ($this->aggresiveSharpening) { # A more aggressive sharpening solution
 
  796         $sharpenMatrix = array( array( -1, -1, -1 ),
 
  798                          array( -1, -1, -1 ) );
 
  802         imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
 
  804       else # More subtle and personally more desirable
 
  806         $sharpness  = $this->findSharp($this->widthOriginal, $this->width);
 
  808         $sharpenMatrix  = array(
 
  810           array(-2, $sharpness + 12, -2), 
 
  813         $divisor    = $sharpness; 
 
  815         imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
 
  820       if ($this->debug) { 
throw new Exception(
'Sharpening required PHP 5.1.0 or greater.'); }
 
  824   ## -------------------------------------------------------- 
  828       $sharpenMatrix  = array(
 
  829         array($level, $level, $level),
 
  830         array($level, (8*$level)+1, $level), 
 
  831         array($level, $level, $level)
 
  836 ## -------------------------------------------------------- 
  838   private function findSharp($orig, $final)
 
  839     # Author:     Ryan Rud (http://adryrun.com) 
  840     # Purpose:    Find optimal sharpness 
  847     $final  = $final * (750.0 / $orig);
 
  849     $b    = -0.27810650887573124;
 
  850     $c    = .00047337278106508946;
 
  852     $result = $a + $b * $final + $c * $final * $final;
 
  857 ## -------------------------------------------------------- 
  859   private function prepOption($option)
 
  860     # Author:     Jarrod Oberto 
  861     # Purpose:    Prep option like change the passed in option to lowercase 
  862     # Param in:   (str/int) $option: eg. 'exact', 'crop'. 0, 4 
  863     # Param out:  lowercase string 
  868     if (is_array($option)) {
 
  869       if (
fix_strtolower($option[0]) == 
'crop' && count($option) == 2) {
 
  872         throw new Exception(
'Crop resize option array is badly formatted.');
 
  874     } 
else if (strpos($option, 
'crop') !== 
false) {
 
  878     if (is_string($option)) {
 
  891 # Preset are pre-defined templates you can apply to your image. 
  893 # These are inteded to be applied to thumbnail images. 
  897   public function borderPreset($preset)
 
  903         $this->addBorder(7, 
'#fff');
 
  904         $this->addBorder(6, 
'#f2f1f0');
 
  905         $this->addBorder(2, 
'#fff');
 
  906         $this->addBorder(1, 
'#ccc');
 
  919   public function addBorder($thickness = 1, $rgbArray = array(255, 255, 255))
 
  920     # Author:     Jarrod Oberto 
  922     # Purpose:    Add a border to the image 
  926     # Notes:    This border is added to the INSIDE of the image 
  929     if ($this->imageResized) {
 
  931       $rgbArray = $this->formatColor($rgbArray);
 
  939       $x2 = ImageSX($this->imageResized) - 1;
 
  940       $y2 = ImageSY($this->imageResized) - 1;
 
  942       $rgbArray = ImageColorAllocate($this->imageResized, $r, $g, $b);
 
  945       for(
$i = 0; 
$i < $thickness; 
$i++) {
 
  946         ImageRectangle($this->imageResized, $x1++, $y1++, $x2--, $y2--, $rgbArray);
 
  956   public function greyScale()
 
  957     # Author:     Jarrod Oberto 
  959     # Purpose:    Make image greyscale 
  966     if ($this->imageResized) {
 
  967       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 
  972   ## -------------------------------------------------------- 
  974   public function greyScaleEnhanced()
 
  975     # Author:     Jarrod Oberto 
  977     # Purpose:    Make image greyscale 
  984     if ($this->imageResized) {
 
  985       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 
  986       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
 
  987       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2);
 
  992   ## -------------------------------------------------------- 
  994   public function greyScaleDramatic()
 
  995   # Alias of gd_filter_monopin 
  997     $this->gd_filter_monopin();
 
 1005   public function blackAndWhite()
 
 1006     # Author:     Jarrod Oberto 
 1008     # Purpose:    Make image black and white 
 1015     if ($this->imageResized) {
 
 1017       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 
 1018       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000);
 
 1028   public function negative()
 
 1029     # Author:     Jarrod Oberto 
 1031     # Purpose:    Make image negative 
 1038     if ($this->imageResized) {
 
 1040       imagefilter($this->imageResized, IMG_FILTER_NEGATE);
 
 1050   public function sepia()
 
 1051     # Author:     Jarrod Oberto 
 1053     # Purpose:    Make image sepia 
 1060     if ($this->imageResized) {
 
 1061       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 
 1062       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10);
 
 1063       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20);
 
 1064       imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15);
 
 1068   ## -------------------------------------------------------- 
 1070   public function sepia2()
 
 1073     if ($this->imageResized) {
 
 1075       $total = imagecolorstotal( $this->imageResized );
 
 1076       for ( 
$i = 0; 
$i < $total; 
$i++ ) {
 
 1077         $index = imagecolorsforindex( $this->imageResized, 
$i );
 
 1078         $red = ( 
$index[
"red"] * 0.393 + 
$index[
"green"] * 0.769 + 
$index[
"blue"] * 0.189 ) / 1.351;
 
 1079         $green = ( 
$index[
"red"] * 0.349 + 
$index[
"green"] * 0.686 + 
$index[
"blue"] * 0.168 ) / 1.203;
 
 1080         $blue = ( 
$index[
"red"] * 0.272 + 
$index[
"green"] * 0.534 + 
$index[
"blue"] * 0.131 ) / 2.140;
 
 1081         imagecolorset( $this->imageResized, 
$i, $red, $green, $blue );
 
 1093   public function vintage()
 
 1094   # Alias of gd_filter_monopin 
 1096     $this->gd_filter_vintage();
 
 1105   public function gd_filter_monopin()
 
 1108     if ($this->imageResized) {
 
 1109       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 
 1110       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15);
 
 1111       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
 
 1112       $this->imageResized = $this->gd_apply_overlay($this->imageResized, 
'vignette', 100);
 
 1116   ## -------------------------------------------------------- 
 1118   public function gd_filter_vintage()
 
 1120     if ($this->imageResized) {
 
 1121       $this->imageResized = $this->gd_apply_overlay($this->imageResized, 
'vignette', 45);
 
 1122       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20);
 
 1123       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35);
 
 1124       imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35);
 
 1125       imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7);
 
 1126       $this->imageResized = $this->gd_apply_overlay($this->imageResized, 
'scratch', 10);
 
 1130   ## -------------------------------------------------------- 
 1133   private function gd_apply_overlay($im, 
$type, $amount)
 
 1135   # Original Author:    Marc Hibbins 
 1136   # License:  Attribution-ShareAlike 3.0 
 1144     $height = imagesy($im);
 
 1147     imagealphablending(
$filter, 
false);
 
 1148     imagesavealpha(
$filter, 
true);
 
 1150     $transparent = imagecolorallocatealpha(
$filter, 255, 255, 255, 127);
 
 1151     imagefilledrectangle(
$filter, 0, 0, 
$width, $height, $transparent);
 
 1154     $overlay = $this->filterOverlayPath . 
'/' . 
$type . 
'.png';
 
 1155     $png = imagecreatefrompng($overlay);
 
 1156     imagecopyresampled(
$filter, $png, 0, 0, 0, 0, 
$width, $height, imagesx($png), imagesy($png));
 
 1158     $comp = imagecreatetruecolor(
$width, $height);
 
 1159     imagecopy($comp, $im, 0, 0, 0, 0, 
$width, $height);
 
 1161     imagecopymerge($im, $comp, 0, 0, 0, 0, 
$width, $height, $amount);
 
 1163     imagedestroy($comp);
 
 1172   public function image_colorize($rgb) {
 
 1173     imageTrueColorToPalette($this->imageResized,
true,256);
 
 1174     $numColors = imageColorsTotal($this->imageResized);
 
 1176     for ($x = 0; $x < $numColors; $x++) {
 
 1177     list($r,$g,$b) = array_values(imageColorsForIndex($this->imageResized,$x));
 
 1180     $grayscale = ($r + $g + $b) / 3 / 0xff;
 
 1182     imageColorSet($this->imageResized,$x,
 
 1183       $grayscale * $rgb[0],
 
 1184       $grayscale * $rgb[1],
 
 1185       $grayscale * $rgb[2]
 
 1198   public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = 
false, $bgColor = 
'#fff', $stretch=
false, $divider = 0)
 
 1202     $rgbArray = $this->formatColor($bgColor);
 
 1203     $r = $rgbArray[
'r'];
 
 1204     $g = $rgbArray[
'g'];
 
 1205     $b = $rgbArray[
'b'];
 
 1208     $li = imagecreatetruecolor($this->width, 1);
 
 1210     $bgc = imagecolorallocate($li, $r, $g, $b);
 
 1211     imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc);
 
 1213     $bg = imagecreatetruecolor($this->width, $reflectionHeight);
 
 1214     $wh = imagecolorallocate($im, 255, 255, 255);
 
 1216     $im = imagerotate($im, -180, $wh);
 
 1217     imagecopyresampled(
$bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
 
 1221     $bg = imagecreatetruecolor($this->width, $reflectionHeight);
 
 1224       imagecopy(
$bg, $im, $x, 0, $this->width-$x -1, 0, 1, $reflectionHeight);
 
 1228     $transaprencyAmount = $this->invertTransparency($startingTransparency, 100);
 
 1233       $step = 100/($reflectionHeight + $startingTransparency);
 
 1235       $step = 100/$reflectionHeight;
 
 1237     for(
$i=0; 
$i<=$reflectionHeight; 
$i++){
 
 1239       if($startingTransparency>100) $startingTransparency = 100;
 
 1240       if($startingTransparency< 1) $startingTransparency = 1;
 
 1241       imagecopymerge(
$bg, $li, 0, 
$i, 0, 0, $this->width, 1, $startingTransparency);
 
 1242       $startingTransparency+=$step;
 
 1246     imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); 
 
 1258       $final = imagecreatetruecolor($this->width, $this->height);
 
 1260       imagecopymerge ($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100);
 
 1261       imagecopymerge ($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100);
 
 1266       $final = imagecreatetruecolor($this->width, $this->height + $y);
 
 1268       imagecopymerge ($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100);
 
 1269       imagecopymerge ($final, $im, 0, $this->height, 0, 0, $x, $y, 100);
 
 1272     $this->imageResized = $final;
 
 1283   public function rotate($value = 90, $bgColor = 
'transparent')
 
 1284     # Author:     Jarrod Oberto 
 1286     # Purpose:    Rotate image 
 1287     # Param in:   (mixed) $degrees: (int) number of degress to rotate image 
 1288   #               (str) param "left": rotate left 
 1289   #               (str) param "right": rotate right 
 1290   #               (str) param "upside": upside-down image 
 1293     # Notes:    The default direction of imageRotate() is counter clockwise. 
 1296     if ($this->imageResized) {
 
 1298       if (is_integer($value)) {
 
 1303       $rgbArray = $this->formatColor($bgColor);
 
 1304       $r = $rgbArray[
'r'];
 
 1305       $g = $rgbArray[
'g'];
 
 1306       $b = $rgbArray[
'b'];
 
 1307       if (isset($rgbArray[
'a'])) {$a = $rgbArray[
'a']; }
 
 1309       if (is_string($value)) {
 
 1331       $degrees = 360 - $degrees;
 
 1334       $bg = ImageColorAllocateAlpha($this->imageResized, $r, $g, $b, $a);
 
 1337       ImageFill($this->imageResized, 0, 0 , 
$bg);
 
 1340       $this->imageResized = imagerotate($this->imageResized, $degrees, 
$bg); 
 
 1343       ImageSaveAlpha($this->imageResized,
true);
 
 1353   public function roundCorners($radius = 5,  $bgColor = 
'transparent')
 
 1354     # Author:     Jarrod Oberto 
 1356     # Purpose:    Create rounded corners on your image 
 1357     # Param in:   (int) radius = the amount of curvature 
 1358   #       (mixed) $bgColor = the corner background color 
 1366     $isTransparent = 
false;
 
 1367     if (!is_array($bgColor)) {
 
 1369         $isTransparent = 
true;
 
 1375     if ($isTransparent) {
 
 1376       $bgColor = $this->findUnusedGreen();
 
 1380     $rgbArray = $this->formatColor($bgColor);
 
 1381     $r = $rgbArray[
'r'];
 
 1382     $g = $rgbArray[
'g'];
 
 1383     $b = $rgbArray[
'b'];
 
 1384     if (isset($rgbArray[
'a'])) {$a = $rgbArray[
'a']; }
 
 1389     $cornerImg = imagecreatetruecolor($radius, $radius);
 
 1399     $maskColor = imagecolorallocate($cornerImg, 0, 0, 0);
 
 1404     imagecolortransparent($cornerImg, $maskColor);
 
 1409     $imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b);
 
 1414     imagefill($cornerImg, 0, 0, $imagebgColor);
 
 1417     imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor );
 
 1421     imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl
 
 1424     $cornerImg = imagerotate($cornerImg, 90, 0);
 
 1425     imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl
 
 1427     $cornerImg = imagerotate($cornerImg, 90, 0);
 
 1428     imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br
 
 1430     $cornerImg = imagerotate($cornerImg, 90, 0);
 
 1431     imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr
 
 1435     if ($isTransparent) {
 
 1437       $this->imageResized = $this->transparentImage($this->imageResized);
 
 1438       imagesavealpha($this->imageResized, 
true);
 
 1448   public function addShadow($shadowAngle=45, $blur=15, $bgColor=
'transparent')
 
 1450   # Author:   Jarrod Oberto (Adapted from Pascal Naidon) 
 1451   # Ref:    http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en 
 1452   # Purpose:  Add a drop shadow to your image 
 1453   # Params in:  (int) $angle: the angle of the shadow 
 1454   #       (int) $blur: the blur distance 
 1455   #       (mixed) $bgColor: the color of the background 
 1461     define(
'STEPS', $blur*2);
 
 1464     $shadowDistance = $blur*0.25;
 
 1467     $blurWidth = $blurHeight = $blur;
 
 1470     if ($shadowAngle == 0) {
 
 1474       $distWidth = $shadowDistance * cos(deg2rad($shadowAngle));
 
 1475       $distHeight = $shadowDistance * sin(deg2rad($shadowAngle));
 
 1481       $rgbArray = $this->formatColor($bgColor);
 
 1482       $r0 = $rgbArray[
'r'];
 
 1483       $g0 = $rgbArray[
'g'];
 
 1484       $b0 = $rgbArray[
'b'];
 
 1493       $newImage = imagecreatetruecolor(
$width, $height);
 
 1498     $rgb = imagecreatetruecolor(
$width+$blurWidth,$height+$blurHeight);
 
 1499     $colour = imagecolorallocate($rgb, 0, 0, 0);
 
 1500     imagefilledrectangle($rgb, 0, 0, 
$width+$blurWidth, $height+$blurHeight, $colour);
 
 1501     $colour = imagecolorallocate($rgb, 255, 255, 255);
 
 1503     imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, 
$width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
 
 1505     imagecopymerge($rgb, $newImage, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, 0,0, 
$width+$blurWidth, $height+$blurHeight, 100);
 
 1509     $shadow = imagecreatetruecolor(
$width+$blurWidth,$height+$blurHeight);
 
 1510       imagealphablending($shadow, 
false);
 
 1511     $colour = imagecolorallocate($shadow, 0, 0, 0);
 
 1512     imagefilledrectangle($shadow, 0, 0, 
$width+$blurWidth, $height+$blurHeight, $colour);
 
 1515     for(
$i=0;
$i<=STEPS;
$i++) {
 
 1517       $t = ((1.0*
$i)/STEPS);
 
 1518       $intensity = 255*$t*$t;
 
 1520       $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
 
 1522         $blurWidth*$t,        $blurHeight,     
 
 1523         $blurWidth,         $blurHeight*$t,  
 
 1525         $width+$blurWidth*(1-$t), $blurHeight,     
 
 1526         $width+$blurWidth*(1-$t), $height,     
 
 1527         $width,           $height+$blurHeight*(1-$t),  
 
 1528         $blurWidth,         $height+$blurHeight*(1-$t),  
 
 1529         $blurWidth*$t,        $height      
 
 1531       imagepolygon($shadow, $points, 8, $colour);
 
 1534     for(
$i=0;
$i<=STEPS;
$i++) {
 
 1536       $t = ((1.0*
$i)/STEPS);
 
 1537         $intensity = 255*$t*$t;
 
 1539       $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
 
 1540       imagefilledarc($shadow, $blurWidth-1, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 180, 268, $colour, IMG_ARC_PIE);
 
 1541       imagefilledarc($shadow, 
$width, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 270, 358, $colour, IMG_ARC_PIE);
 
 1542       imagefilledarc($shadow, 
$width, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 0, 90, $colour, IMG_ARC_PIE);
 
 1543       imagefilledarc($shadow, $blurWidth-1, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 90, 180, $colour, IMG_ARC_PIE);
 
 1547     $colour = imagecolorallocate($shadow, 255, 255, 255);
 
 1548     imagefilledrectangle($shadow, $blurWidth, $blurHeight, 
$width, $height, $colour);
 
 1549     imagefilledrectangle($shadow, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, 
$width+$blurWidth*0.5-1-$distWidth, $height+$blurHeight*0.5-1-$distHeight, $colour);
 
 1553         imagealphablending($rgb, 
false);
 
 1555         for ($theX=0;$theX<imagesx($rgb);$theX++){
 
 1556       for ($theY=0;$theY<imagesy($rgb);$theY++){
 
 1559         $colArray = imagecolorat($rgb,$theX,$theY);
 
 1560         $r = ($colArray >> 16) & 0xFF;
 
 1561         $g = ($colArray >> 8) & 0xFF;
 
 1562         $b = $colArray & 0xFF;
 
 1565         $colArray = imagecolorat($shadow,$theX,$theY);
 
 1566         $a = $colArray & 0xFF;
 
 1567         $a = 127-floor($a/2);
 
 1572           $myColour = imagecolorallocatealpha($rgb,$r,$g,$b,$a);
 
 1574           $myColour = imagecolorallocate($rgb,$r*(1.0-$t)+$r0*$t,$g*(1.0-$t)+$g0*$t,$b*(1.0-$t)+$b0*$t);
 
 1578         imagesetpixel($rgb, $theX, $theY, $myColour);
 
 1582     imagealphablending($rgb, 
true);
 
 1583     imagesavealpha($rgb, 
true);
 
 1585     $this->imageResized = $rgb;
 
 1588     imagedestroy($newImage);
 
 1589     imagedestroy($shadow);
 
 1597   public function addCaptionBox($side=
'b', $thickness=50, $padding=0, $bgColor=
'#000', $transaprencyAmount=30)
 
 1599   # Author:   Jarrod Oberto 
 1601   # Purpose:  Add a caption box 
 1602   # Params in:  (str) $side: the side to add the caption box (t, r, b, or l). 
 1603   #       (int) $thickness: how thick you want the caption box to be. 
 1604   #       (mixed) $bgColor: The color of the caption box. 
 1605   #       (int) $transaprencyAmount: The amount of transparency to be 
 1614       $rgbArray = $this->formatColor($bgColor);
 
 1615       $r = $rgbArray[
'r'];
 
 1616       $g = $rgbArray[
'g'];
 
 1617       $b = $rgbArray[
'b'];
 
 1619       $positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding);
 
 1622       $this->captionBoxPositionArray = $positionArray;
 
 1625       $transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, 
false);
 
 1626       $transparent = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount);
 
 1627       imagefilledrectangle($this->imageResized, $positionArray[
'x1'], $positionArray[
'y1'], $positionArray[
'x2'], $positionArray[
'y2'], $transparent);
 
 1630   ## -------------------------------------------------------- 
 1632   public function addTextToCaptionBox(
$text, $fontColor=
'#fff', $fontSize = 12, $angle = 0, $font = null)
 
 1634   # Author:   Jarrod Oberto 
 1636   # Purpose:  Simplify adding text to a caption box by automatically 
 1637   #       locating the center of the caption box 
 1638   # Params in:  The usually text paams (less a couple) 
 1645     if (count($this->captionBoxPositionArray) == 4) {
 
 1646       $x1 = $this->captionBoxPositionArray[
'x1'];
 
 1647       $x2 = $this->captionBoxPositionArray[
'x2'];
 
 1648       $y1 = $this->captionBoxPositionArray[
'y1'];
 
 1649       $y2 = $this->captionBoxPositionArray[
'y2'];
 
 1651       if ($this->debug) { 
throw new Exception(
'No caption box found.'); }
else{ 
return false; }
 
 1656     $font = $this->getTextFont($font);
 
 1659     $textSizeArray = $this->getTextSize($fontSize, $angle, $font, 
$text);
 
 1660     $textWidth = $textSizeArray[
'width'];
 
 1661     $textHeight = $textSizeArray[
'height'];
 
 1664     $boxXMiddle = (($x2 - $x1) / 2);
 
 1665     $boxYMiddle = (($y2 - $y1) / 2);
 
 1668     $xPos = ($x1 + $boxXMiddle) - ($textWidth/2);
 
 1669     $yPos = ($y1 + $boxYMiddle) - ($textHeight/2);
 
 1671     $pos = $xPos . 
'x' . $yPos;
 
 1673     $this->addText(
$text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font);
 
 1677   ## -------------------------------------------------------- 
 1679   private function calculateCaptionBoxPosition($side, $thickness, $padding)
 
 1681     $positionArray = array();
 
 1685         $positionArray[
'x1'] = 0;
 
 1686         $positionArray[
'y1'] = $padding;
 
 1688         $positionArray[
'y2'] = $thickness + $padding;
 
 1691         $positionArray[
'x1'] = $this->width - $thickness - $padding;
 
 1692         $positionArray[
'y1'] = 0;
 
 1693         $positionArray[
'x2'] = $this->width - $padding;
 
 1697         $positionArray[
'x1'] = 0;
 
 1698         $positionArray[
'y1'] = $this->height - $thickness - $padding;
 
 1700         $positionArray[
'y2'] = $this->height - $padding;
 
 1703         $positionArray[
'x1'] = $padding;
 
 1704         $positionArray[
'y1'] = 0;
 
 1705         $positionArray[
'x2'] = $thickness + $padding;
 
 1713     return $positionArray;
 
 1721   public function getExif(
$debug=
false)
 
 1722     # Author:     Jarrod Oberto 
 1724     # Purpose:    Get image EXIF data 
 1726     # Param out:  An associate array of EXIF data 
 1729     # 23 May 13 : added orientation flag -jco 
 1736     if (!$this->testEXIFInstalled()) { 
if (
$debug) { 
throw new Exception(
'The EXIF Library is not installed.'); }
else{ 
return array(); }};
 
 1737     if (!file_exists($this->fileName)) { 
if (
$debug) { 
throw new Exception(
'Image not found.'); }
else{ 
return array(); }};
 
 1738     if ($this->fileExtension != 
'.jpg') { 
if (
$debug) { 
throw new Exception(
'Metadata not supported for this image type.'); }
else{ 
return array(); }};
 
 1739     $exifData = exif_read_data($this->fileName, 
'IFD0');
 
 1742     $ev = $exifData[
'ApertureValue'];
 
 1743     $apPeicesArray = explode(
'/', $ev);
 
 1744     if (count($apPeicesArray) == 2) {
 
 1745       $apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . 
' EV';
 
 1746     } 
else { $apertureValue = 
'';}
 
 1749     $focalLength = $exifData[
'FocalLength'];
 
 1750     $flPeicesArray = explode(
'/', $focalLength);
 
 1751     if (count($flPeicesArray) == 2) {
 
 1752       $focalLength = $flPeicesArray[0] / $flPeicesArray[1] . 
'.0 mm';
 
 1753     } 
else { $focalLength = 
'';}
 
 1756     $fNumber = $exifData[
'FNumber'];
 
 1757     $fnPeicesArray = explode(
'/', $fNumber);
 
 1758     if (count($fnPeicesArray) == 2) {
 
 1759       $fNumber = $fnPeicesArray[0] / $fnPeicesArray[1];
 
 1760     } 
else { $fNumber = 
'';}
 
 1763     if (isset($exifData[
'ExposureProgram'])) { $ep =  $exifData[
'ExposureProgram']; }
 
 1764     if (isset($ep)) { $ep = $this->resolveExposureProgram($ep); }
 
 1768     $mm = $exifData[
'MeteringMode'];
 
 1769     $mm = $this->resolveMeteringMode($mm);
 
 1772     $flash = $exifData[
'Flash'];
 
 1773     $flash = $this->resolveFlash($flash);
 
 1776     if (isset($exifData[
'Make'])) {
 
 1777       $exifDataArray[
'make'] = $exifData[
'Make'];
 
 1778     } 
else { $exifDataArray[
'make'] = 
''; }
 
 1780     if (isset($exifData[
'Model'])) {
 
 1781       $exifDataArray[
'model'] = $exifData[
'Model'];
 
 1782     } 
else { $exifDataArray[
'model'] = 
''; }
 
 1784     if (isset($exifData[
'DateTime'])) {
 
 1785       $exifDataArray[
'date'] = $exifData[
'DateTime'];
 
 1786     } 
else { $exifDataArray[
'date'] = 
''; }
 
 1788     if (isset($exifData[
'ExposureTime'])) {
 
 1789       $exifDataArray[
'exposure time'] = $exifData[
'ExposureTime'] . 
' sec.';
 
 1790     } 
else { $exifDataArray[
'exposure time'] = 
''; }
 
 1792     if ($apertureValue != 
'') {
 
 1793       $exifDataArray[
'aperture value'] = $apertureValue;
 
 1794     } 
else { $exifDataArray[
'aperture value'] = 
''; }
 
 1796     if (isset($exifData[
'COMPUTED'][
'ApertureFNumber'])) {
 
 1797       $exifDataArray[
'f-stop'] = $exifData[
'COMPUTED'][
'ApertureFNumber'];
 
 1798     } 
else { $exifDataArray[
'f-stop'] = 
''; }
 
 1800     if (isset($exifData[
'FNumber'])) {
 
 1801       $exifDataArray[
'fnumber'] = $exifData[
'FNumber'];
 
 1802     } 
else { $exifDataArray[
'fnumber'] = 
''; }
 
 1804     if ($fNumber != 
'') {
 
 1805       $exifDataArray[
'fnumber value'] = $fNumber;
 
 1806     } 
else { $exifDataArray[
'fnumber value'] = 
''; }
 
 1808     if (isset($exifData[
'ISOSpeedRatings'])) {
 
 1809       $exifDataArray[
'iso'] = $exifData[
'ISOSpeedRatings'];
 
 1810     } 
else { $exifDataArray[
'iso'] = 
''; }
 
 1812     if ($focalLength != 
'') {
 
 1813       $exifDataArray[
'focal length'] = $focalLength;
 
 1814     } 
else { $exifDataArray[
'focal length'] = 
''; }
 
 1817       $exifDataArray[
'exposure program'] = $ep;
 
 1818     } 
else { $exifDataArray[
'exposure program'] = 
''; }
 
 1821       $exifDataArray[
'metering mode'] = $mm;
 
 1822     } 
else { $exifDataArray[
'metering mode'] = 
''; }
 
 1825       $exifDataArray[
'flash status'] = $flash;
 
 1826     } 
else { $exifDataArray[
'flash status'] = 
''; }
 
 1828     if (isset($exifData[
'Artist'])) {
 
 1829       $exifDataArray[
'creator'] = $exifData[
'Artist'] ;
 
 1830     } 
else { $exifDataArray[
'creator'] = 
''; }
 
 1832     if (isset($exifData[
'Copyright'])) {
 
 1833       $exifDataArray[
'copyright'] = $exifData[
'Copyright'];
 
 1834     } 
else { $exifDataArray[
'copyright'] = 
''; }
 
 1837     if (isset($exifData[
'Orientation'])) {
 
 1838         $exifDataArray[
'orientation'] = $exifData[
'Orientation'];
 
 1839     } 
else { $exifDataArray[
'orientation'] = 
''; }
 
 1841     return $exifDataArray;
 
 1844   ## -------------------------------------------------------- 
 1846   private function resolveExposureProgram($ep)
 
 1856         $ep = 
'normal program';
 
 1859         $ep = 
'aperture priority';
 
 1862         $ep = 
'shutter priority';
 
 1865         $ep = 
'creative program';
 
 1868         $ep = 
'action program';
 
 1871         $ep = 
'portrait mode';
 
 1874         $ep = 
'landscape mode';
 
 1884   ## -------------------------------------------------------- 
 1886   private function resolveMeteringMode($mm)
 
 1896         $mm = 
'center weighted average';
 
 1921   ## -------------------------------------------------------- 
 1923   private function resolveFlash($flash)
 
 1927         $flash = 
'flash did not fire';
 
 1930         $flash = 
'flash fired';
 
 1933         $flash = 
'strobe return light not detected';
 
 1936         $flash = 
'strobe return light detected';
 
 1939         $flash = 
'flash fired, compulsory flash mode';
 
 1942         $flash = 
'flash fired, compulsory flash mode, return light not detected';
 
 1945         $flash = 
'flash fired, compulsory flash mode, return light detected';
 
 1948         $flash = 
'flash did not fire, compulsory flash mode';
 
 1951         $flash = 
'flash did not fire, auto mode';
 
 1954         $flash = 
'flash fired, auto mode';
 
 1957         $flash = 
'flash fired, auto mode, return light not detected';
 
 1960         $flash = 
'flash fired, auto mode, return light detected';
 
 1963         $flash = 
'no flash function';
 
 1966         $flash = 
'flash fired, red-eye reduction mode';
 
 1969         $flash = 
'flash fired, red-eye reduction mode, return light not detected';
 
 1972         $flash = 
'flash fired, red-eye reduction mode, return light detected';
 
 1975         $flash = 
'flash fired, compulsory flash mode, red-eye reduction mode';
 
 1978         $flash = 
'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
 
 1981         $flash = 
'flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
 
 1984         $flash = 
'flash fired, auto mode, red-eye reduction mode';
 
 1987         $flash = 
'flash fired, auto mode, return light not detected, red-eye reduction mode';
 
 1990         $flash = 
'flash fired, auto mode, return light detected, red-eye reduction mode';
 
 2011   public function writeIPTCcaption($value)
 
 2014     $this->writeIPTC(120, $value);
 
 2017   ## -------------------------------------------------------- 
 2019   public function writeIPTCwriter($value)
 
 2024   ## -------------------------------------------------------- 
 2026   private function writeIPTC($dat, $value)
 
 2031     $caption_block = $this->iptc_maketag(2, $dat, $value);
 
 2032     $image_string = iptcembed($caption_block, $this->fileName);
 
 2033     file_put_contents(
'iptc.jpg', $image_string);
 
 2036 ## -------------------------------------------------------- 
 2038   private function iptc_maketag($rec,$dat,$val)
 
 2039   # Author:   Thies C. Arntzen 
 2040   # Purpose:    Function to format the new IPTC text 
 2041   # Param in:   $rec: Application record. (We’re working with #2) 
 2042   #       $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM 
 2044   #         http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf 
 2045   #       $val: Value/data/text. Make sure this is within the length 
 2046   #         constraints of the IPTC IIM specification 
 2047   # Ref:      http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/ 
 2048   #       http://php.net/manual/en/function.iptcembed.php 
 2051     $len = strlen($val);
 
 2053       return chr(0x1c).chr($rec).chr($dat).
 
 2058       return chr(0x1c).chr($rec).chr($dat).
 
 2059       chr(0x80).chr(0x04).
 
 2060       chr(($len >> 24) & 0xff).
 
 2061       chr(($len >> 16) & 0xff).
 
 2062       chr(($len >> 8 ) & 0xff).
 
 2063       chr(($len ) & 0xff).
 
 2080   public function addText(
$text, $pos = 
'20x20', $padding = 0, $fontColor=
'#fff', $fontSize = 12, $angle = 0, $font = null)
 
 2081     # Author:     Jarrod Oberto 
 2083     # Purpose:    Add text to an image 
 2086     # Reference:  http://php.net/manual/en/function.imagettftext.php 
 2087     # Notes:      Make sure you supply the font. 
 2092     $rgbArray = $this->formatColor($fontColor);
 
 2093     $r = $rgbArray[
'r'];
 
 2094     $g = $rgbArray[
'g'];
 
 2095     $b = $rgbArray[
'b'];
 
 2098     $font = $this->getTextFont($font);
 
 2101     $textSizeArray = $this->getTextSize($fontSize, $angle, $font, 
$text);
 
 2102     $textWidth = $textSizeArray[
'width'];
 
 2103     $textHeight = $textSizeArray[
'height'];
 
 2106     $posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, 
false);
 
 2107     $x = $posArray[
'width'];
 
 2108     $y = $posArray[
'height'];
 
 2110     $fontColor = imagecolorallocate($this->imageResized, $r, $g, $b);
 
 2113     imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, 
$text);
 
 2116   ## -------------------------------------------------------- 
 2118   private function getTextFont($font)
 
 2125     putenv(
'GDFONTPATH=' . realpath(
'.'));
 
 2128     if ($font == null || !file_exists($font)) {
 
 2131       $font = $fontPath . 
'/arimo.ttf';
 
 2134       if (!file_exists($font)) {
 
 2137         if ($this->debug) { 
throw new Exception(
'Font not found'); }
else{ 
return false; }
 
 2145   ## -------------------------------------------------------- 
 2147   private function getTextSize($fontSize, $angle, $font, 
$text)
 
 2151     $box = @imageTTFBbox($fontSize, $angle, $font, 
$text);
 
 2154     $textWidth = abs($box[4] - $box[0]);
 
 2157     $textHeight = abs($box[5] - $box[1]);
 
 2159     return array(
'height' => $textHeight, 
'width' => $textWidth);
 
 2167   public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0)
 
 2168     # Author:     Jarrod Oberto 
 2170     # Purpose:    Add watermark image 
 2171     # Param in:   (str) $watermark: The watermark image 
 2172   #       (str) $pos: Could be a pre-determined position such as: 
 2180   #           b  = bottom (middle), 
 2182   #         Or, it could be a co-ordinate position such as: 50x100 
 2184   #       (int) $padding: If using a pre-determined position you can 
 2185   #         adjust the padding from the edges by passing an amount 
 2186   #         in pixels. If using co-ordinates, this value is ignored. 
 2188     # Reference:  http://www.php.net/manual/en/image.examples-watermark.php 
 2189     # Notes:      Based on example in reference. 
 2195     $stamp = $this->openImage ($watermarkImage);    # stamp
 
 2199     $sx = imagesx($stamp);
 
 2200     $sy = imagesy($stamp);
 
 2203     $posArray = $this->calculatePosition($pos, $padding, $sx, $sy);
 
 2204     $x = $posArray[
'width'];
 
 2205     $y = $posArray[
'height'];
 
 2210       $opacity = $this->invertTransparency($opacity, 100);
 
 2211       $this->filterOpacity($stamp, $opacity);
 
 2215     imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp));
 
 2219   ## -------------------------------------------------------- 
 2221   private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = 
true)
 
 2223   # Author:   Jarrod Oberto 
 2225   # Purpose:  Calculate the x, y pixel cordinates of the asset to place 
 2226   # Params in:  (str) $pos: Either something like: "tl", "l", "br" or an 
 2227   #         exact position like: "100x50" 
 2228   #       (int) $padding: The amount of padding from the edge. Only 
 2229   #         used for the predefined $pos. 
 2230   #       (int) $assetWidth: The width of the asset to add to the image 
 2231   #       (int) $assetHeight: The height of the asset to add to the image 
 2232   #       (bol) $upperLeft: if true, the asset will be positioned based 
 2233   #         on the upper left x, y coords. If false, it means you're 
 2234   #         using the lower left as the basepoint and this will 
 2235   #         convert it to the upper left position 
 2237   # NOTE: this is done from the UPPER left corner!! But will convert lower 
 2238   #   left basepoints to upper left if $upperleft is set to false 
 2245     if (strstr($pos, 
'x')) {
 
 2246       $pos = str_replace(
' ', 
'', $pos);
 
 2248       $xyArray = explode(
'x', $pos);
 
 2249       list(
$width, $height) = $xyArray;
 
 2256           $height = 0 + $padding;
 
 2260           $width = ($this->width / 2) - ($assetWidth / 2);
 
 2261           $height = 0 + $padding;
 
 2265           $width = $this->width - $assetWidth - $padding;
 
 2266           $height = 0 + $padding;;
 
 2271           $height = ($this->height / 2) - ($assetHeight / 2);
 
 2275           $width = ($this->width / 2) - ($assetWidth / 2);
 
 2276           $height = ($this->height / 2) - ($assetHeight / 2);
 
 2280           $width = $this->width - $assetWidth - $padding;
 
 2281           $height = ($this->height / 2) - ($assetHeight / 2);
 
 2286           $height = $this->height - $assetHeight - $padding;
 
 2290           $width = ($this->width / 2) - ($assetWidth / 2);
 
 2291           $height = $this->height - $assetHeight - $padding;
 
 2295           $width = $this->width - $assetWidth - $padding;
 
 2296           $height = $this->height - $assetHeight - $padding;
 
 2307       $height = $height + $assetHeight;
 
 2310     return array(
'width' => 
$width, 
'height' => $height);
 
 2314   ## -------------------------------------------------------- 
 2316   private function filterOpacity(&$img, $opacity = 75)
 
 2318   # Author:     aiden dot mail at freemail dot hu 
 2319   # Author date:  29-03-08 08:16 
 2320   # Date added:   08-05-11 
 2321   # Purpose:    Change opacity of image 
 2322   # Params in:    $img: Image resource id 
 2323   #         (int) $opacity: the opacity amount: 0-100, 100 being not opaque. 
 2324   # Params out:   (bool) true on success, else false 
 2325   # Ref:      http://www.php.net/manual/en/function.imagefilter.php#82162 
 2330     if (!isset($opacity)) {
 
 2334     if ($opacity == 100) {
 
 2345     imagealphablending($img, 
false);
 
 2349     for ($x = 0; $x < $w; $x++)
 
 2350       for ($y = 0; $y < $h; $y++) {
 
 2351         $alpha = ( imagecolorat($img, $x, $y) >> 24 ) & 0xFF;
 
 2352         if ($alpha < $minalpha) {
 
 2358     for ($x = 0; $x < $w; $x++) {
 
 2359       for ($y = 0; $y < $h; $y++) {
 
 2361         $colorxy = imagecolorat($img, $x, $y);
 
 2362         $alpha = ( $colorxy >> 24 ) & 0xFF;
 
 2364         if ($minalpha !== 127) {
 
 2365           $alpha = 127 + 127 * $opacity * ( $alpha - 127 ) / ( 127 - $minalpha );
 
 2367           $alpha += 127 * $opacity;
 
 2370         $alphacolorxy = imagecolorallocatealpha($img, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha);
 
 2372         if (!imagesetpixel($img, $x, $y, $alphacolorxy)) {
 
 2382 ## -------------------------------------------------------- 
 2384     private function openImage(
$file)
 
 2385     # Author:     Jarrod Oberto 
 2395     if (!file_exists(
$file) && !$this->checkStringStartsWith(
'http://', 
$file)) { 
if ($this->debug) { 
throw new Exception(
'Image not found.'); }
else{ 
throw new Exception(); }};
 
 2398         $extension = strrchr(
$file, 
'.');
 
 2404                 $img = @imagecreatefromjpeg(
$file);
 
 2407                 $img = @imagecreatefromgif(
$file);
 
 2410                 $img = @imagecreatefrompng(
$file);
 
 2413                 $img = @$this->imagecreatefrombmp(
$file);
 
 2416                 $img = @$this->imagecreatefrompsd(
$file);
 
 2430 ## -------------------------------------------------------- 
 2432   public function reset()
 
 2434   # Author:   Jarrod Oberto 
 2436   # Purpose:  Reset the resource (allow further editing) 
 2445 ## -------------------------------------------------------- 
 2447     public function saveImage($savePath, $imageQuality=
"100")
 
 2448     # Author:     Jarrod Oberto 
 2450     # Purpose:    Saves the image 
 2451     # Param in:   $savePath: Where to save the image including filename: 
 2452     #             $imageQuality: image quality you want the image saved at 0-100 
 2455     # Notes:    * gif doesn't have a quality parameter 
 2456   #       * jpg has a quality setting 0-100 (100 being the best) 
 2457     #       * png has a quality setting 0-9 (0 being the best) 
 2459   #             * bmp files have no native support for bmp files. We use a 
 2460   #       third party class to save as bmp. 
 2464     if (!is_resource($this->imageResized)) { 
if ($this->debug) { 
throw new Exception(
'saveImage: This is not a resource.'); }
else{ 
throw new Exception(); }}
 
 2465     $fileInfoArray = pathInfo($savePath);
 
 2467     if (!is_writable($fileInfoArray[
'dirname'])) {  
if ($this->debug) { 
throw new Exception(
'The path is not writable. Please check your permissions.'); }
else{ 
throw new Exception(); }}
 
 2470         $extension = strrchr($savePath, 
'.');
 
 2479         $this->checkInterlaceImage($this->isInterlace);
 
 2480         if (imagetypes() & IMG_JPG) {
 
 2481           imagejpeg($this->imageResized, $savePath, $imageQuality);
 
 2482         } 
else { 
$error = 
'jpg'; }
 
 2486         $this->checkInterlaceImage($this->isInterlace);
 
 2487         if (imagetypes() & IMG_GIF) {
 
 2488           imagegif($this->imageResized, $savePath);
 
 2489         } 
else { 
$error = 
'gif'; }
 
 2494         $scaleQuality = round(($imageQuality/100) * 9);
 
 2497         $invertScaleQuality = 9 - $scaleQuality;
 
 2499         $this->checkInterlaceImage($this->isInterlace);
 
 2500         if (imagetypes() & IMG_PNG) {
 
 2501            imagepng($this->imageResized, $savePath, $invertScaleQuality);
 
 2502         } 
else { 
$error = 
'png'; }
 
 2506         file_put_contents($savePath, $this->GD2BMPstring($this->imageResized));
 
 2514         $this->errorArray[] = 
'This file type (' . $extension . 
') is not supported. File not saved.';
 
 2522       $this->errorArray[] = 
$error . 
' support is NOT enabled. File not saved.';
 
 2526 ## -------------------------------------------------------- 
 2528   public function displayImage($fileType = 
'jpg', $imageQuality=
"100")
 
 2529     # Author:     Jarrod Oberto 
 2531     # Purpose:    Display images directly to the browser 
 2532     # Param in:   The image type you want to display 
 2539     if (!is_resource($this->imageResized)) { 
if ($this->debug) { 
throw new Exception(
'saveImage: This is not a resource.'); }
else{ 
throw new Exception(); }}
 
 2545         header(
'Content-type: image/jpeg');
 
 2546         imagejpeg($this->imageResized, 
'', $imageQuality);
 
 2549         header(
'Content-type: image/gif');
 
 2550         imagegif($this->imageResized);
 
 2553         header(
'Content-type: image/png');
 
 2556         $scaleQuality = round(($imageQuality/100) * 9);
 
 2559         $invertScaleQuality = 9 - $scaleQuality;
 
 2561         imagepng($this->imageResized, 
'', $invertScaleQuality);
 
 2564         echo 
'bmp file format is not supported.';
 
 2578 ## -------------------------------------------------------- 
 2580   public function setTransparency($bool)
 
 2583     $this->keepTransparency = $bool;
 
 2586 ## -------------------------------------------------------- 
 2588   public function setFillColor($value)
 
 2590     # Param in:   (mixed) $value: (array) Could be an array of RGB 
 2591   #               (str) Could be hex #ffffff or #fff, fff, ffffff 
 2593   # If the keepTransparency is set to false, then no transparency is to be used. 
 2594   # This is ideal when you want to save as jpg. 
 2596   # this method allows you to set the background color to use instead of 
 2600     $colorArray = $this->formatColor($value);
 
 2601     $this->fillColorArray = $colorArray;
 
 2604 ## -------------------------------------------------------- 
 2606   public function setCropFromTop($value)
 
 2609     $this->cropFromTopPercent = $value;
 
 2612 ## -------------------------------------------------------- 
 2614     public function testGDInstalled()
 
 2615     # Author:     Jarrod Oberto 
 2617     # Purpose:    Test to see if GD is installed 
 2619     # Param out:  (bool) True is gd extension loaded otherwise false 
 2624         if(extension_loaded(
'gd') && function_exists(
'gd_info'))
 
 2626             $gdInstalled = 
true;
 
 2630             $gdInstalled = 
false;
 
 2633         return $gdInstalled;
 
 2636 ## -------------------------------------------------------- 
 2638     public function testEXIFInstalled()
 
 2639     # Author:     Jarrod Oberto 
 2641     # Purpose:    Test to see if EXIF is installed 
 2643     # Param out:  (bool) True is exif extension loaded otherwise false 
 2648         if(extension_loaded(
'exif'))
 
 2650             $exifInstalled = 
true;
 
 2654             $exifInstalled = 
false;
 
 2657         return $exifInstalled;
 
 2660 ## -------------------------------------------------------- 
 2662     public function testIsImage(
$image)
 
 2663     # Author:     Jarrod Oberto 
 2665     # Purpose:    Test if file is an image 
 2674             $fileIsImage = 
true;
 
 2678             $fileIsImage = 
false;
 
 2681         return $fileIsImage;
 
 2684 ## -------------------------------------------------------- 
 2686     public function testFunct()
 
 2687     # Author:     Jarrod Oberto 
 2689     # Purpose:    Test Function 
 2699 ## -------------------------------------------------------- 
 2701     public function setForceStretch($value)
 
 2702     # Author:     Jarrod Oberto 
 2705     # Param in:   (bool) $value 
 2711         $this->forceStretch = $value;
 
 2714 ## -------------------------------------------------------- 
 2717     # Author:     Jarrod Oberto 
 2729 ## -------------------------------------------------------- 
 2731   public function getFileName()
 
 2732     # Author:     Jarrod Oberto 
 2744 ## -------------------------------------------------------- 
 2746   public function getHeight()
 
 2751 ## -------------------------------------------------------- 
 2753   public function getWidth()
 
 2758 ## -------------------------------------------------------- 
 2760   public function getOriginalHeight()
 
 2765 ## -------------------------------------------------------- 
 2767   public function getOriginalWidth()
 
 2772 ## -------------------------------------------------------- 
 2774   public function getErrors()
 
 2775     # Author:     Jarrod Oberto 
 2777     # Purpose:    Returns the error array 
 2779     # Param out:  Array of errors 
 2787 ## -------------------------------------------------------- 
 2789   private function checkInterlaceImage($isEnabled)
 
 2790   # jpg will use progressive (they don't use interace) 
 2793       imageinterlace($this->imageResized, $isEnabled);
 
 2797 ## -------------------------------------------------------- 
 2799   protected function formatColor($value)
 
 2800     # Author:     Jarrod Oberto 
 2802     # Purpose:    Determine color method passed in and return color as RGB 
 2803     # Param in:   (mixed) $value: (array) Could be an array of RGB 
 2804   #               (str) Could be hex #ffffff or #fff, fff, ffffff 
 2810     $rgbArray = array();
 
 2813     if (is_array($value)) {
 
 2815       if (key($value) == 0 && count($value) == 3) {
 
 2817         $rgbArray[
'r'] = $value[0];
 
 2818         $rgbArray[
'g'] = $value[1];
 
 2819         $rgbArray[
'b'] = $value[2];
 
 2836       $rgbArray = $this -> hex2dec($value);
 
 2842   ## -------------------------------------------------------- 
 2844   function hex2dec($hex)
 
 2845   # Purpose:  Convert #hex color to RGB 
 2847     $color = str_replace(
'#', 
'', $hex);
 
 2849     if (strlen($color) == 3) {
 
 2850       $color = $color . $color;
 
 2854       'r' => hexdec(substr($color, 0, 2)),
 
 2855       'g' => hexdec(substr($color, 2, 2)),
 
 2856       'b' => hexdec(substr($color, 4, 2)),
 
 2862   ## -------------------------------------------------------- 
 2864   private function createImageColor ($colorArray)
 
 2866     $r = $colorArray[
'r'];
 
 2867     $g = $colorArray[
'g'];
 
 2868     $b = $colorArray[
'b'];
 
 2870     return imagecolorallocate($this->imageResized, $r, $g, $b);
 
 2873   ## -------------------------------------------------------- 
 2875   private function testColorExists($colorArray)
 
 2877     $r = $colorArray[
'r'];
 
 2878     $g = $colorArray[
'g'];
 
 2879     $b = $colorArray[
'b'];
 
 2881     if (imagecolorexact($this->imageResized, $r, $g, $b) == -1) {
 
 2888   ## -------------------------------------------------------- 
 2890   private function findUnusedGreen()
 
 2891   # Purpose:  We find a green color suitable to use like green-screen effect. 
 2892   #     Therefore, the color must not exist in the image. 
 2898       $greenChroma = array(0, $green, 0);
 
 2899       $colorArray = $this->formatColor($greenChroma);
 
 2900       $match = $this->testColorExists($colorArray);
 
 2903     } 
while ($match == 
false && $green > 0);
 
 2907       $greenChroma = array(0, $green, 0);
 
 2910     return $greenChroma;
 
 2913   ## -------------------------------------------------------- 
 2915   private function findUnusedBlue()
 
 2916   # Purpose:  We find a green color suitable to use like green-screen effect. 
 2917   #     Therefore, the color must not exist in the image. 
 2923       $blueChroma = array(0, 0, $blue);
 
 2924       $colorArray = $this->formatColor($blueChroma);
 
 2925       $match = $this->testColorExists($colorArray);
 
 2928     } 
while ($match == 
false && $blue > 0);
 
 2932       $blueChroma = array(0, 0, $blue);
 
 2938   ## -------------------------------------------------------- 
 2940   private function invertTransparency($value, $originalMax, $invert=
true)
 
 2941   # Purpose:  This does two things: 
 2942   #       1) Convert the range from 0-127 to 0-100 
 2943   #       2) Inverts value to 100 is not transparent while 0 is fully 
 2944   #          transparent (like Photoshop) 
 2947     if ($value > $originalMax) {
 
 2948       $value = $originalMax;
 
 2957       return $originalMax - (($value/100) * $originalMax);
 
 2959       return ($value/100) * $originalMax;
 
 2963   ## -------------------------------------------------------- 
 2965   private function transparentImage($src)
 
 2971     for ($x = 0; $x < imagesx($src); ++$x) {
 
 2972       for ($y = 0; $y < imagesy($src); ++$y) {
 
 2973         $color = imagecolorat($src, $x, $y);
 
 2974         $r = ($color >> 16) & 0xFF;
 
 2975         $g = ($color >> 8) & 0xFF;
 
 2977         for (
$i = 0; 
$i < 270; 
$i++) {
 
 2979           if ($r == 0 && $g == 255 && $b == 0) {
 
 2981             $trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127);
 
 2982             imagefill($src, $x, $y, $trans_colour);
 
 2991   ## -------------------------------------------------------- 
 2993   function checkStringStartsWith($needle, $haystack)
 
 2994   # Check if a string starts with a specific pattern 
 2996     return (substr($haystack, 0, strlen($needle))==$needle);
 
 3004   private function GD2BMPstring(&$gd_image)
 
 3005     # Author:     James Heinrich 
 3006     # Purpose:    Save file as type bmp 
 3007     # Param in:   The image canvas (passed as ref) 
 3010     # Notes:    This code was stripped out of two external files 
 3011   #       (phpthumb.bmp.php,phpthumb.functions.php) and added below to 
 3012   #       avoid dependancies. 
 3015     $imageX = ImageSX($gd_image);
 
 3016     $imageY = ImageSY($gd_image);
 
 3019     for ($y = ($imageY - 1); $y >= 0; $y--) {
 
 3021       for ($x = 0; $x < $imageX; $x++) {
 
 3022         $argb = $this->GetPixelColor($gd_image, $x, $y);
 
 3023         $thisline .= chr($argb[
'blue']).chr($argb[
'green']).chr($argb[
'red']);
 
 3025       while (strlen($thisline) % 4) {
 
 3026         $thisline .= 
"\x00";
 
 3031     $bmpSize = strlen($BMP) + 14 + 40;
 
 3033     $BITMAPFILEHEADER  = 
'BM';                                    
 
 3034     $BITMAPFILEHEADER .= $this->LittleEndian2String($bmpSize, 4); 
 
 3035     $BITMAPFILEHEADER .= $this->LittleEndian2String(       0, 2); 
 
 3036     $BITMAPFILEHEADER .= $this->LittleEndian2String(       0, 2); 
 
 3037     $BITMAPFILEHEADER .= $this->LittleEndian2String(      54, 4); 
 
 3040     $BITMAPINFOHEADER  = $this->LittleEndian2String(      40, 4); 
 
 3041     $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageX, 4); 
 
 3042     $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageY, 4); 
 
 3043     $BITMAPINFOHEADER .= $this->LittleEndian2String(       1, 2); 
 
 3044     $BITMAPINFOHEADER .= $this->LittleEndian2String(      24, 2); 
 
 3045     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); 
 
 3046     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); 
 
 3047     $BITMAPINFOHEADER .= $this->LittleEndian2String(    2835, 4); 
 
 3048     $BITMAPINFOHEADER .= $this->LittleEndian2String(    2835, 4); 
 
 3049     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); 
 
 3050     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); 
 
 3052     return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP;
 
 3055 ## -------------------------------------------------------- 
 3057   private function GetPixelColor(&$img, $x, $y)
 
 3058     # Author:     James Heinrich 
 3066     if (!is_resource($img)) {
 
 3069     return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
 
 3072 ## -------------------------------------------------------- 
 3074   private function LittleEndian2String($number, $minbytes=1)
 
 3075     # Author:     James Heinrich 
 3076     # Purpose:    BMP SUPPORT (SAVING) 
 3084     while ($number > 0) {
 
 3085       $intstring = $intstring.chr($number & 255);
 
 3088     return str_pad($intstring, $minbytes, 
"\x00", STR_PAD_RIGHT);
 
 3096   private function ImageCreateFromBMP($filename)
 
 3098     # Date:     The 15th of June 2005 
 3100     # Purpose:    To create an image from a BMP file. 
 3101     # Param in:   BMP file to open. 
 3102     # Param out:  Return a resource like the other ImageCreateFrom functions 
 3103     # Reference:  http://us3.php.net/manual/en/function.imagecreate.php#53879 
 3104   # Bug fix:    Author:   domelca at terra dot es 
 3105   #       Date:   06 March 2008 
 3106   #       Fix:    Correct 16bit BMP support 
 3112     if (! $f1 = fopen($filename,
"rb")) 
return FALSE;
 
 3115     $FILE = unpack(
"vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
 
 3116     if ($FILE[
'file_type'] != 19778) 
return FALSE;
 
 3119     $BMP = unpack(
'Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
 
 3120            '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
 
 3121            '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
 
 3122     $BMP[
'colors'] = pow(2,$BMP[
'bits_per_pixel']);
 
 3124     if ($BMP[
'size_bitmap'] == 0) $BMP[
'size_bitmap'] = $FILE[
'file_size'] - $FILE[
'bitmap_offset'];
 
 3126     $BMP[
'bytes_per_pixel'] = $BMP[
'bits_per_pixel']/8;
 
 3127     $BMP[
'bytes_per_pixel2'] = ceil($BMP[
'bytes_per_pixel']);
 
 3128     $BMP[
'decal'] = ($BMP[
'width']*$BMP[
'bytes_per_pixel']/4);
 
 3129        $BMP[
'decal'] -= floor($BMP[
'width']*$BMP[
'bytes_per_pixel']/4);
 
 3130     $BMP[
'decal'] = 4-(4*$BMP[
'decal']);
 
 3132     if ($BMP[
'decal'] == 4) $BMP[
'decal'] = 0;
 
 3136     if ($BMP[
'colors'] < 16777216)
 
 3138       $PALETTE = unpack(
'V'.$BMP[
'colors'], fread($f1,$BMP[
'colors']*4));
 
 3142     $IMG = fread($f1,$BMP[
'size_bitmap']);
 
 3145     $res = imagecreatetruecolor($BMP[
'width'],$BMP[
'height']);
 
 3147     $Y = $BMP[
'height']-1;
 
 3151       while ($X < $BMP[
'width'])
 
 3153         if ($BMP[
'bits_per_pixel'] == 24)
 
 3154           $COLOR = unpack(
"V",substr($IMG,$P,3).$VIDE);
 
 3155         elseif ($BMP[
'bits_per_pixel'] == 16)
 
 3174           $COLOR = unpack(
"v",substr($IMG,$P,2));
 
 3175           $blue = ($COLOR[1] & 0x001f) << 3;
 
 3176           $green = ($COLOR[1] & 0x07e0) >> 3;
 
 3177           $red = ($COLOR[1] & 0xf800) >> 8;
 
 3178           $COLOR[1] = $red * 65536 + $green * 256 + $blue;
 
 3181         elseif ($BMP[
'bits_per_pixel'] == 8)
 
 3183           $COLOR = unpack(
"n",$VIDE.substr($IMG,$P,1));
 
 3184           $COLOR[1] = $PALETTE[$COLOR[1]+1];
 
 3186         elseif ($BMP[
'bits_per_pixel'] == 4)
 
 3188           $COLOR = unpack(
"n",$VIDE.substr($IMG,floor($P),1));
 
 3189           if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; 
else $COLOR[1] = ($COLOR[1] & 0x0F);
 
 3190           $COLOR[1] = $PALETTE[$COLOR[1]+1];
 
 3192         elseif ($BMP[
'bits_per_pixel'] == 1)
 
 3194           $COLOR = unpack(
"n",$VIDE.substr($IMG,floor($P),1));
 
 3195           if     (($P*8)%8 == 0) $COLOR[1] =  $COLOR[1]        >>7;
 
 3196           elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
 
 3197           elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
 
 3198           elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
 
 3199           elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
 
 3200           elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
 
 3201           elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
 
 3202           elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
 
 3203           $COLOR[1] = $PALETTE[$COLOR[1]+1];
 
 3208         imagesetpixel(
$res,$X,$Y,$COLOR[1]);
 
 3210         $P += $BMP['bytes_per_pixel'];
 
 3227   private function imagecreatefrompsd(
$fileName)
 
 3228   # Author:     Tim de Koning 
 3230   # Purpose:    To create an image from a PSD file. 
 3231   # Param in:   PSD file to open. 
 3232   # Param out:  Return a resource like the other ImageCreateFrom functions 
 3233   # Reference:  http://www.kingsquare.nl/phppsdreader 
 3237     if (file_exists($this->psdReaderPath)) {
 
 3240       include_once($this->psdReaderPath);
 
 3242       $psdReader = 
new PhpPsdReader(
$fileName);
 
 3244       if (isset($psdReader->infoArray[
'error'])) 
return '';
 
 3245       else return $psdReader->getImage();
 
 3251 ## -------------------------------------------------------- 
 3253     public function __destruct() {
 
 3254     if (is_resource($this->imageResized)) {
 
 3255       imagedestroy($this->imageResized);
 
 3259 ## -------------------------------------------------------- 
if(empty($settings['ROOT_PATH'])) elseif(empty($settings['DB_PARAMETERS'])) $error
getOptimalCrop($newWidth, $newHeight)#Author
if(!$dbm->isConnectable()) $res
if(!isset($xoops->paths[$path_type])) if($path_type== 'var') $file
getSizeByAuto($newWidth, $newHeight)#Author
keepTransparancy($width, $height, $im)#Author
getSizeByFixedWidth($newWidth, $newHeight)
__construct($fileName)#Author
getSizeByFixedHeight($newWidth, $newHeight)
if($xoops->isActiveModule('images')) return false
if($xoops->isUser()) else
getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos='m')##Author
resizeImage($newWidth, $newHeight, $option=0, $sharpen=false, $autoRotate=false)#Author
cropImage($newWidth, $newHeight, $cropPos= 'm')#Author
getDimensions($newWidth, $newHeight, $option)#Author
crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)#Author