Advertisement
Guest User

Untitled

a guest
Nov 3rd, 2012
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 49.95 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Image_Toolbox.class.php -- PHP image manipulation class
  4.  *
  5.  * Copyright (C) 2003 Martin Theimer <pappkamerad@decoded.net>
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License <http://www.opensource.org/gpl-license.html>
  15.  * for more details..
  16.  *
  17.  * The latest version of Image_Toolbox can be obtained from:
  18.  * http://sourceforge.net/projects/image-toolbox
  19.  * http://www.phpclasses.org/image_toolbox
  20.  *
  21.  * @author Martin Theimer <pappkamerad@decoded.net>
  22.  * @copyright Copyright (C) 2003 Martin Theimer
  23.  * @version 1.1.0
  24.  * @package Image_Toolbox
  25.  * @link http://sourceforge.net/projects/image-toolbox
  26.  */
  27.  
  28. // $Id: Image_Toolbox.class.php,v 1.9 2003/12/05 19:34:01 pappkamerad Exp $
  29.  
  30. if (!defined('IMAGE_TOOLBOX_DEFAULT_JPEG_QUALITY')) {
  31.     define('IMAGE_TOOLBOX_DEFAULT_JPEG_QUALITY', 75);
  32. }
  33. if (!defined('IMAGE_TOOLBOX_DEFAULT_8BIT_COLORS')) {
  34.     define('IMAGE_TOOLBOX_DEFAULT_8BIT_COLORS', 256);
  35. }
  36. if (!defined('IMAGE_TOOLBOX_BIAS_HORIZONTAL')) {
  37.     define('IMAGE_TOOLBOX_BIAS_HORIZONTAL', 1);
  38. }
  39. if (!defined('IMAGE_TOOLBOX_BIAS_VERTICAL')) {
  40.     define('IMAGE_TOOLBOX_BIAS_VERTICAL', 0);
  41. }
  42. if (!defined('IMAGE_TOOLBOX_BLEND_COPY')) {
  43.     define('IMAGE_TOOLBOX_BLEND_COPY', 1);
  44. }
  45. if (!defined('IMAGE_TOOLBOX_BLEND_MULTIPLY')) {
  46.     define('IMAGE_TOOLBOX_BLEND_MULTIPLY', 2);
  47. }
  48. if (!defined('IMAGE_TOOLBOX_BLEND_SCREEN')) {
  49.     define('IMAGE_TOOLBOX_BLEND_SCREEN', 3);
  50. }
  51. if (!defined('IMAGE_TOOLBOX_BLEND_DIFFERENCE')) {
  52.     define('IMAGE_TOOLBOX_BLEND_DIFFERENCE', 4);
  53. }
  54. if (!defined('IMAGE_TOOLBOX_BLEND_NEGATION')) {
  55.     define('IMAGE_TOOLBOX_BLEND_NEGATION', 5);
  56. }
  57. if (!defined('IMAGE_TOOLBOX_BLEND_EXCLUTION')) {
  58.     define('IMAGE_TOOLBOX_BLEND_EXCLUSION', 6);
  59. }
  60. if (!defined('IMAGE_TOOLBOX_BLEND_OVERLAY')) {
  61.     define('IMAGE_TOOLBOX_BLEND_OVERLAY', 7);
  62. }
  63.  
  64. /**
  65.  * PHP image manipulation class
  66.  *
  67.  * This class provides an easy to use library to the PHP GD-based imagefunctions
  68.  *
  69.  * @author Martin Theimer <pappkamerad@decoded.net>
  70.  * @copyright 2003, Martin Theimer
  71.  * @package Image_Toolbox
  72.  * @link http://sourceforge.net/projects/image-toolbox
  73.  * @version 1.1.0
  74.  */
  75. class Image_Toolbox {
  76.  
  77.     /**
  78.      * The prefix for every error message
  79.      *
  80.      * @access private
  81.      * @var string
  82.      */
  83.     var $_error_prefix = 'Image: ';
  84.    
  85.     /**
  86.      * Defines imagetypes and how they are supported by the server
  87.      *
  88.      * @access private
  89.      * @var array
  90.      */
  91.     var $_types = array (
  92.         1 => array (
  93.             'ext' => 'gif',
  94.             'mime' => 'image/gif',
  95.             'supported' => 0
  96.         ),
  97.         2 => array (
  98.             'ext' => 'jpg',
  99.             'mime' => 'image/jpeg',
  100.             'supported' => 0
  101.         ),
  102.         3 => array (
  103.             'ext' => 'png',
  104.             'mime' => 'image/png',
  105.             'supported' => 0
  106.         )
  107.     );
  108.    
  109.     /**
  110.      * Which PHP image resize function to be used
  111.      * imagecopyresampled only supported with GD >= 2.0
  112.      *
  113.      * @access private
  114.      * @var string
  115.      */
  116.     var $_resize_function = 'imagecopyresampled';
  117.  
  118.     /**
  119.      * Stores all image resource data
  120.      *
  121.      * @access private
  122.      * @var array
  123.      */
  124.     var $_img = array (
  125.         'main' => array (
  126.             'resource' => 0,
  127.             'width' => 0,
  128.             'height' => 0,
  129.             'bias' => 0,
  130.             'aspectratio' => 0,
  131.             'type' => 0,
  132.             'output_type' => 0,
  133.             'indexedcolors' => 0,
  134.             'color' => -1
  135.         )
  136.     );
  137.    
  138.     /**
  139.      * Which PHP image create function to be used
  140.      * imagecreatetruecolor only supported with GD >= 2.0
  141.      *
  142.      * @access private
  143.      * @var string
  144.      */
  145.     var $_imagecreatefunction = '';
  146.    
  147.     /**
  148.      * The class constructor.
  149.      *
  150.      * Determines the image features of the server and sets the according values.<br>
  151.      * Additionally you can specify a image to be created/loaded. like {@link addImage() addImage}.
  152.      *
  153.      * If no parameter is given, no image resource will be generated<br>
  154.      * Or:<br>
  155.      * <i>string</i> <b>$file</b> imagefile to load<br>
  156.      * Or:<br>
  157.      * <i>integer</i> <b>$width</b> imagewidth of new image to be created<br>
  158.      * <i>integer</i> <b>$height</b> imageheight of new image to be created<br>
  159.      * <i>string</i> <b>$fillcolor</b> optional fill the new image with this color (hexformat, e.g. '#FF0000')<br>
  160.      */
  161.     function Image_Toolbox() {
  162.         $args = func_get_args();
  163.         $argc = func_num_args();
  164.        
  165.         //get GD information. see what types we can handle
  166.         $gd_info = function_exists('gd_info') ? gd_info() : $this->_gd_info();
  167.         preg_match("/\A[\D]*([\d+\.]*)[\D]*\Z/", $gd_info['GD Version'], $matches);
  168.         list($this->_gd_version_string, $this->_gd_version_number) = $matches;
  169.         $this->_gd_version = substr($this->_gd_version_number, 0, strpos($this->_gd_version_number, '.'));
  170.         if ($this->_gd_version >= 2) {
  171.             $this->_imagecreatefunction = 'imagecreatetruecolor';
  172.             $this->_resize_function = 'imagecopyresampled';
  173.         } else {
  174.             $this->_imagecreatefunction = 'imagecreate';
  175.             $this->_resize_function = 'imagecopyresized';
  176.         }
  177.                        
  178.         $this->_gd_ttf = $gd_info['FreeType Support'];
  179.         $this->_gd_ps = $gd_info['T1Lib Support'];
  180.         if ($gd_info['GIF Read Support']) {
  181.             $this->_types[1]['supported'] = 1;
  182.             if ($gd_info['GIF Create Support']) {
  183.                 $this->_types[1]['supported'] = 2;
  184.             }
  185.         }
  186.         if (isset($gd_info['JPG Support']) || isset($gd_info['JPEG Support'])) {
  187.             $this->_types[2]['supported'] = 2;
  188.         }
  189.         if ($gd_info['PNG Support']) {
  190.             $this->_types[3]['supported'] = 2;
  191.         }
  192.        
  193.         //load or create main image
  194.         if ($argc == 0) {
  195.             return true;
  196.         } else {
  197.             if ($this->_addImage($argc, $args)) {
  198.                 foreach ($this->_img['operator'] as $key => $value) {
  199.                     $this->_img['main'][$key] = $value;
  200.                 }
  201.                 $this->_img['main']['output_type'] = $this->_img['main']['type'];
  202.                 unset($this->_img['operator']);
  203.                 return true;
  204.             } else {
  205.                 trigger_error($this->_error_prefix . 'No appropriate constructor found.', E_USER_ERROR);
  206.                 return null;
  207.             }
  208.         }
  209.     }
  210.  
  211.     /**
  212.      * Returns an assocative array with information about the image features of this server
  213.      *
  214.      * Array values:
  215.      * <ul>
  216.      * <li>'gd_version' -> what GD version is installed on this server (e.g. 2.0)</li>
  217.      * <li>'gif' -> 0 = not supported, 1 = reading is supported, 2 = creating is supported</li>
  218.      * <li>'jpg' -> 0 = not supported, 1 = reading is supported, 2 = creating is supported</li>
  219.      * <li>'png' -> 0 = not supported, 1 = reading is supported, 2 = creating is supported</li>
  220.      * <li>'ttf' -> TTF text creation. true = supported, false = not supported
  221.      * </ul>
  222.      *
  223.      * @return array
  224.      */
  225.     function getServerFeatures() {
  226.         $features = array();
  227.         $features['gd_version'] = $this->_gd_version_number;
  228.         $features['gif'] = $this->_types[1]['supported'];
  229.         $features['jpg'] = $this->_types[2]['supported'];
  230.         $features['png'] = $this->_types[3]['supported'];
  231.         $features['ttf'] = $this->_gd_ttf;
  232.         return $features;
  233.     }
  234.  
  235.     /**
  236.      * Flush all image resources and init a new one
  237.      *
  238.      * Parameter:<br>
  239.      * <i>string</i> <b>$file</b> imagefile to load<br>
  240.      * Or:<br>
  241.      * <i>integer</i> <b>$width</b> imagewidth of new image to be created<br>
  242.      * <i>integer</i> <b>$height</b> imageheight of new image to be created<br>
  243.      * <i>string</i> <b>$fillcolor</b> optional fill the new image with this color (hexformat, e.g. '#FF0000')<br>
  244.      */
  245.     function newImage() {
  246.         $args = func_get_args();
  247.         $argc = func_num_args();
  248.        
  249.         if ($this->_addImage($argc, $args)) {
  250.             foreach ($this->_img['operator'] as $key => $value) {
  251.                 $this->_img['main'][$key] = $value;
  252.             }
  253.             $this->_img['main']['output_type'] = $this->_img['main']['type'];
  254.             unset($this->_img['operator']);
  255.             return true;
  256.         } else {
  257.             trigger_error($this->_error_prefix . 'No appropriate constructor found.', E_USER_ERROR);
  258.             return null;
  259.         }
  260.     }
  261.  
  262.     /**
  263.      * Reimplements the original PHP {@link gd_info()} function for older PHP versions
  264.      *
  265.      * @access private
  266.      * @return array associative array with info about the GD library of the server
  267.      */
  268.     function _gd_info() {
  269.         $array = array(
  270.             "GD Version" => "",
  271.             "FreeType Support" => false,
  272.             "FreeType Linkage" => "",
  273.             "T1Lib Support" => false,
  274.             "GIF Read Support" => false,
  275.             "GIF Create Support" => false,
  276.             "JPG Support" => false,
  277.             "PNG Support" => false,
  278.             "WBMP Support" => false,
  279.             "XBM Support" => false
  280.         );
  281.        
  282.         $gif_support = 0;
  283.         ob_start();
  284.         eval("phpinfo();");
  285.         $info = ob_get_contents();
  286.         ob_end_clean();
  287.      
  288.         foreach(explode("\n", $info) as $line) {
  289.             if(strpos($line, "GD Version") !== false)
  290.                 $array["GD Version"] = trim(str_replace("GD Version", "", strip_tags($line)));
  291.             if(strpos($line, "FreeType Support") !== false)
  292.                 $array["FreeType Support"] = trim(str_replace("FreeType Support", "", strip_tags($line)));
  293.             if(strpos($line, "FreeType Linkage") !== false)
  294.                 $array["FreeType Linkage"] = trim(str_replace("FreeType Linkage", "", strip_tags($line)));
  295.             if(strpos($line, "T1Lib Support") !== false)
  296.                 $array["T1Lib Support"] = trim(str_replace("T1Lib Support", "", strip_tags($line)));
  297.             if(strpos($line, "GIF Read Support") !== false)
  298.                 $array["GIF Read Support"] = trim(str_replace("GIF Read Support", "", strip_tags($line)));
  299.             if(strpos($line, "GIF Create Support") !== false)
  300.                 $array["GIF Create Support"] = trim(str_replace("GIF Create Support", "", strip_tags($line)));
  301.             if(strpos($line, "GIF Support") !== false)
  302.                 $gif_support = trim(str_replace("GIF Support", "", strip_tags($line)));
  303.             if(strpos($line, "JPG Support") !== false)
  304.                 $array["JPG Support"] = trim(str_replace("JPG Support", "", strip_tags($line)));
  305.             if(strpos($line, "PNG Support") !== false)
  306.                 $array["PNG Support"] = trim(str_replace("PNG Support", "", strip_tags($line)));
  307.             if(strpos($line, "WBMP Support") !== false)
  308.                 $array["WBMP Support"] = trim(str_replace("WBMP Support", "", strip_tags($line)));
  309.             if(strpos($line, "XBM Support") !== false)
  310.                 $array["XBM Support"] = trim(str_replace("XBM Support", "", strip_tags($line)));
  311.         }
  312.        
  313.         if($gif_support === "enabled") {
  314.             $array["GIF Read Support"] = true;
  315.             $array["GIF Create Support"] = true;
  316.         }
  317.  
  318.         if($array["FreeType Support"] === "enabled") {
  319.             $array["FreeType Support"] = true;
  320.         }
  321.  
  322.         if($array["T1Lib Support"] === "enabled") {
  323.             $array["T1Lib Support"] = true;
  324.         }
  325.        
  326.         if($array["GIF Read Support"] === "enabled") {
  327.             $array["GIF Read Support"] = true;
  328.         }
  329.  
  330.         if($array["GIF Create Support"] === "enabled") {
  331.             $array["GIF Create Support"] = true;
  332.         }
  333.  
  334.         if($array["JPG Support"] === "enabled") {
  335.             $array["JPG Support"] = true;
  336.         }
  337.            
  338.         if($array["PNG Support"] === "enabled") {
  339.             $array["PNG Support"] = true;
  340.         }
  341.            
  342.         if($array["WBMP Support"] === "enabled") {
  343.             $array["WBMP Support"] = true;
  344.         }
  345.            
  346.         if($array["XBM Support"] === "enabled") {
  347.             $array["XBM Support"] = true;
  348.         }
  349.  
  350.         return $array;
  351.     }
  352.  
  353.     /**
  354.      * Convert a color defined in hexvalues to the PHP color format
  355.      *
  356.      * @access private
  357.      * @param string $hex color value in hexformat (e.g. '#FF0000')
  358.      * @return integer color value in PHP format
  359.      */
  360.     function _hexToPHPColor($hex) {
  361.         $length = strlen($hex);
  362.         $dr = hexdec(substr($hex, $length - 6, 2));
  363.         $dg = hexdec(substr($hex, $length - 4, 2));
  364.         $db = hexdec(substr($hex, $length - 2, 2));
  365.         $color = ($dr << 16) + ($dg << 8) + $db;
  366.         return $color;
  367.     }
  368.    
  369.     /**
  370.      * Convert a color defined in hexvalues to corresponding dezimal values
  371.      *
  372.      * @access private
  373.      * @param string $hex color value in hexformat (e.g. '#FF0000')
  374.      * @return array associative array with color values in dezimal format (fields: 'red', 'green', 'blue')
  375.      */
  376.     function _hexToDecColor($hex) {
  377.         $length = strlen($hex);
  378.         $color['red'] = hexdec(substr($hex, $length - 6, 2));
  379.         $color['green'] = hexdec(substr($hex, $length - 4, 2));
  380.         $color['blue'] = hexdec(substr($hex, $length - 2, 2));
  381.         return $color;
  382.     }
  383.  
  384.     /**
  385.      * Generate a new image resource based on the given parameters
  386.      *
  387.      * Parameter:
  388.      * <i>string</i> <b>$file</b> imagefile to load<br>
  389.      * Or:<br>
  390.      * <i>integer</i> <b>$width</b> imagewidth of new image to be created<br>
  391.      * <i>integer</i> <b>$height</b> imageheight of new image to be created<br>
  392.      * <i>string</i> <b>$fillcolor</b> optional fill the new image with this color (hexformat, e.g. '#FF0000')<br>
  393.      *
  394.      * @access private
  395.      */
  396.     function _addImage($argc, $args) {
  397.         if (($argc == 2 || $argc == 3) && is_int($args[0]) && is_int($args[1]) && (is_string($args[2]) || !isset($args[2]))) {
  398.             //neues leeres bild mit width und height (fillcolor optional)
  399.             $this->_img['operator']['width'] = $args[0];
  400.             $this->_img['operator']['height'] = $args[1];
  401.             ($this->_img['operator']['width'] >= $this->_img['operator']['height']) ? ($this->_img['operator']['bias'] = IMAGE_TOOLBOX_BIAS_HORIZONTAL) : ($this->_img['operator']['bias'] = IMAGE_TOOLBOX_BIAS_VERTICAL);
  402.             $this->_img['operator']['aspectratio'] = $this->_img['operator']['width'] / $this->_img['operator']['height'];
  403.             $this->_img['operator']['indexedcolors'] = 0;
  404.             $functionname = $this->_imagecreatefunction;
  405.             $this->_img['operator']['resource'] = $functionname($this->_img['operator']['width'], $this->_img['operator']['height']);
  406.             // set default type jpg.
  407.             $this->_img['operator']['type'] = 2;
  408.             if (isset($args[2]) && is_string($args[2])) {
  409.                 //neues bild mit farbe fllen
  410.                 $fillcolor = $this->_hexToPHPColor($args[2]);
  411.                 imagefill($this->_img['operator']['resource'], 0, 0, $fillcolor);
  412.                 $this->_img['operator']['color'] = $fillcolor;
  413.             } else {
  414.                 $this->_img['operator']['color'] = 0;
  415.             }
  416.         } elseif ($argc == 1 && is_string($args[0])) {
  417.             //bild aus datei laden. width und height original gr”sse
  418.             $this->_img['operator'] = $this->_loadFile($args[0]);
  419.             $this->_img['operator']['indexedcolors'] = imagecolorstotal($this->_img['operator']['resource']);
  420.             $this->_img['operator']['color'] = -1;
  421.         } else {
  422.             return false;
  423.         }
  424.         return true;
  425.     }
  426.  
  427.     /**
  428.      * Loads a image file
  429.      *
  430.      * @access private
  431.      * @param string $filename imagefile to load
  432.      * @return array associative array with the loaded filedata
  433.      */
  434.     function _loadFile($filename) {
  435.         if (file_exists($filename)) {
  436.             $info = getimagesize($filename);
  437.             $filedata['width'] = $info[0];
  438.             $filedata['height'] = $info[1];
  439.             ($filedata['width'] >= $filedata['height']) ? ($filedata['bias'] = IMAGE_TOOLBOX_BIAS_HORIZONTAL) : ($filedata['bias'] = IMAGE_TOOLBOX_BIAS_VERTICAL);
  440.             $filedata['aspectratio'] = $filedata['width'] / $filedata['height'];
  441.             $filedata['type'] = $info[2];
  442.  
  443.             if ($this->_types[$filedata['type']]['supported'] < 1) {
  444.                 trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$filedata['type']]['ext'].') not supported for reading.', E_USER_ERROR);
  445.                 return null;
  446.             }
  447.             switch ($filedata['type']) {
  448.                 case 1:
  449.                     $dummy = imagecreatefromgif($filename);
  450.                     $functionname = $this->_imagecreatefunction;
  451.                     $filedata['resource'] = $functionname($filedata['width'], $filedata['height']);
  452.                     imagecopy($filedata['resource'], $dummy, 0, 0, 0, 0, $filedata['width'], $filedata['height']);
  453.                     imagedestroy($dummy);
  454.                     break;
  455.                    
  456.                 case 2:
  457.                     $filedata['resource'] = imagecreatefromjpeg($filename);
  458.                     break;
  459.                    
  460.                 case 3:
  461.                     $dummy = imagecreatefrompng($filename);
  462.                     if (imagecolorstotal($dummy) != 0) {
  463.                         $functionname = $this->_imagecreatefunction;
  464.                         $filedata['resource'] = $functionname($filedata['width'], $filedata['height']);
  465.                         imagecopy($filedata['resource'], $dummy, 0, 0, 0, 0, $filedata['width'], $filedata['height']);
  466.                     } else {
  467.                         $filedata['resource'] = $dummy;
  468.                     }
  469.                     unset($dummy);
  470.                     break;
  471.                    
  472.                 default:
  473.                     trigger_error($this->_error_prefix . 'Imagetype not supported.', E_USER_ERROR);
  474.                     return null;
  475.             }
  476.             return $filedata;
  477.         } else {
  478.             trigger_error($this->_error_prefix . 'Imagefile (' . $filename . ') does not exist.', E_USER_ERROR);
  479.             return null;
  480.         }
  481.     }
  482.    
  483.     /**
  484.      * Output a image to the browser
  485.      *
  486.      * $output_type can be one of the following:<br>
  487.      * <ul>
  488.      * <li>'gif' -> gif image (if supported) (8-bit indexed colors)</li>
  489.      * <li>'png' -> png image (if supported) (truecolor)</li>
  490.      * <li>'png8' -> png image (if supported) (8-bit indexed colors)</li>
  491.      * <li>'jpg' -> jpeg image (if supported) (truecolor)</li>
  492.      * </ul>
  493.      * (default: same as original)
  494.      *
  495.      * $dither:<br>
  496.      * If this is true than dither is used on the conversion from truecolor to 8-bit indexed imageformats (png8, gif)<br>
  497.      * (default = false)
  498.      *
  499.      * @param string|integer $output_type type of outputted image
  500.      * @param integer $output_quality jpeg quality of outputted image (default: IMAGE_TOOLBOX_DEFAULT_JPEG_QUALITY)
  501.      * @param bool $dither use dither
  502.      * @return bool true on success, otherwise false
  503.      */
  504.     function output($output_type = false, $output_quality = false, $dither = false) {
  505.         if ($output_type === false) {
  506.             $output_type = $this->_img['main']['output_type'];
  507.         }
  508.         switch ($output_type) {
  509.             case 1:
  510.             case 'gif':
  511.             case 'GIF':
  512.                 if ($this->_types[1]['supported'] < 2) {
  513.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  514.                     return null;
  515.                 }
  516.                 header ('Content-type: ' . $this->_types[$output_type]['mime']);
  517.                 if ($this->_gd_version >= 2) {
  518.                     if ($this->_img['main']['indexedcolors'] == 0) {
  519.                         $dummy = imagecreatetruecolor($this->_img['main']['width'], $this->_img['main']['height']);
  520.                         imagecopy($dummy, $this->_img['main']['resource'], 0, 0, 0, 0, $this->_img['main']['width'], $this->_img['main']['height']);
  521.                         if ($output_quality === false) {
  522.                             $output_quality = IMAGE_TOOLBOX_DEFAULT_8BIT_COLORS;
  523.                         }
  524.                         imagetruecolortopalette($dummy, $dither, $output_quality);
  525.                     }
  526.                     imagegif($dummy);
  527.                     imagedestroy($dummy);
  528.                 }
  529.                 else {
  530.                     imagegif($this->_img['main']['resource']);
  531.                 }
  532.                 break;
  533.            
  534.             case 2:
  535.             case '2':
  536.             case 'jpg':
  537.             case 'jpeg':
  538.             case 'JPG':
  539.             case 'JPEG':
  540.                 if ($this->_types[2]['supported'] < 2) {
  541.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  542.                     return null;
  543.                 }
  544.                 header ('Content-type: ' . $this->_types[$output_type]['mime']);
  545.                 if ($output_quality === false) {
  546.                     $output_quality = IMAGE_TOOLBOX_DEFAULT_JPEG_QUALITY;
  547.                 }
  548.                 imagejpeg($this->_img['main']['resource'], '', $output_quality);
  549.                 break;
  550.                
  551.             case 3:
  552.             case '3':
  553.             case 'png':
  554.             case 'PNG':
  555.             case 'png24':
  556.             case 'PNG24':
  557.                 if ($this->_types[3]['supported'] < 2) {
  558.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  559.                     return null;
  560.                 }
  561.                 header ('Content-type: ' . $this->_types[$output_type]['mime']);
  562.                 imagepng($this->_img['main']['resource']);
  563.                 break;
  564.                
  565.             case 4:
  566.             case '4':
  567.             case 'png8':
  568.             case 'PNG8':
  569.                 if ($this->_types[3]['supported'] < 2) {
  570.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  571.                     return null;
  572.                 }
  573.                 header ('Content-type: ' . $this->_types[$output_type]['mime']);
  574.                 if ($this->_gd_version >= 2) {
  575.                     if ($this->_img['main']['indexedcolors'] == 0) {
  576.                         $dummy = imagecreatetruecolor($this->_img['main']['width'], $this->_img['main']['height']);
  577.                         imagecopy($dummy, $this->_img['main']['resource'], 0, 0, 0, 0, $this->_img['main']['width'], $this->_img['main']['height']);
  578.                         if ($output_quality === false) {
  579.                             $output_quality = IMAGE_TOOLBOX_DEFAULT_8BIT_COLORS;
  580.                         }
  581.                         imagetruecolortopalette($dummy, $dither, $output_quality);
  582.                     }
  583.                     imagepng($dummy);
  584.                     imagedestroy($dummy);
  585.                 }
  586.                 else {
  587.                     imagepng($this->_img['main']['resource']);
  588.                 }
  589.                 break;
  590.                
  591.             default:
  592.                 trigger_error($this->_error_prefix . 'Output-Imagetype not supported.', E_USER_ERROR);
  593.                 return null;
  594.         }
  595.         return true;
  596.     }
  597.    
  598.     /**
  599.      * Save a image to disk
  600.      *
  601.      * $output_type can be one of the following:<br>
  602.      * <ul>
  603.      * <li>'gif' -> gif image (if supported) (8-bit indexed colors)</li>
  604.      * <li>'png' -> png image (if supported) (truecolor)</li>
  605.      * <li>'png8' -> png image (if supported) (8-bit indexed colors)</li>
  606.      * <li>'jpg' -> jpeg image (if supported) (truecolor)</li>
  607.      * </ul>
  608.      * (default: same as original)
  609.      *
  610.      * $dither:<br>
  611.      * If this is true than dither is used on the conversion from truecolor to 8-bit indexed imageformats (png8, gif)<br>
  612.      * (default = false)
  613.      *
  614.      * @param string $filename filename of saved image
  615.      * @param string|integer $output_type type of saved image
  616.      * @param integer $output_quality jpeg quality of saved image (default: IMAGE_TOOLBOX_DEFAULT_JPEG_QUALITY)
  617.      * @param bool $dither use dither
  618.      * @return bool true on success, otherwise false
  619.      */
  620.     function save($filename, $output_type = false, $output_quality = false, $dither = false) {
  621.         if ($output_type === false) {
  622.             $output_type = $this->_img['main']['output_type'];
  623.         }
  624.         switch ($output_type) {
  625.             case 1:
  626.             case 'gif':
  627.             case 'GIF':
  628.                 if ($this->_types[1]['supported'] < 2) {
  629.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  630.                     return null;
  631.                 }
  632.                 if ($this->_gd_version >= 2) {
  633.                     if ($this->_img['main']['indexedcolors'] == 0) {
  634.                         $dummy = imagecreatetruecolor($this->_img['main']['width'], $this->_img['main']['height']);
  635.                         imagecopy($dummy, $this->_img['main']['resource'], 0, 0, 0, 0, $this->_img['main']['width'], $this->_img['main']['height']);
  636.                         if ($output_quality === false) {
  637.                             $output_quality = IMAGE_TOOLBOX_DEFAULT_8BIT_COLORS;
  638.                         }
  639.                         imagetruecolortopalette($dummy, $dither, $output_quality);
  640.                     }
  641.                     imagegif($dummy, $filename);
  642.                     imagedestroy($dummy);
  643.                 }
  644.                 else {
  645.                     imagegif($this->_img['main']['resource']);
  646.                 }
  647.                 break;
  648.            
  649.             case 2:
  650.             case '2':
  651.             case 'jpg':
  652.             case 'jpeg':
  653.             case 'JPG':
  654.             case 'JPEG':
  655.                 if ($this->_types[2]['supported'] < 2) {
  656.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  657.                     return null;
  658.                 }
  659.                 if ($output_quality === false) {
  660.                     $output_quality = IMAGE_TOOLBOX_DEFAULT_JPEG_QUALITY;
  661.                 }
  662.                 imagejpeg($this->_img['main']['resource'], $filename, $output_quality);
  663.                 break;
  664.                
  665.             case 3:
  666.             case '3':
  667.             case 'png':
  668.             case 'PNG':
  669.             case 'png24':
  670.             case 'PNG24':
  671.                 if ($this->_types[3]['supported'] < 2) {
  672.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  673.                     return null;
  674.                 }
  675.                 header ('Content-type: ' . $this->_types[$output_type]['mime']);
  676.                 imagepng($this->_img['main']['resource'], $filename);
  677.                 break;
  678.                
  679.             case 4:
  680.             case '4':
  681.             case 'png8':
  682.             case 'PNG8':
  683.                 if ($this->_types[3]['supported'] < 2) {
  684.                     trigger_error($this->_error_prefix . 'Imagetype ('.$this->_types[$output_type]['ext'].') not supported for creating/writing.', E_USER_ERROR);
  685.                     return null;
  686.                 }
  687.                 if ($this->_gd_version >= 2) {
  688.                     if ($this->_img['main']['indexedcolors'] == 0) {
  689.                         $dummy = imagecreatetruecolor($this->_img['main']['width'], $this->_img['main']['height']);
  690.                         imagecopy($dummy, $this->_img['main']['resource'], 0, 0, 0, 0, $this->_img['main']['width'], $this->_img['main']['height']);
  691.                         if ($output_quality === false) {
  692.                             $output_quality = IMAGE_TOOLBOX_DEFAULT_8BIT_COLORS;
  693.                         }
  694.                         imagetruecolortopalette($dummy, $dither, $output_quality);
  695.                     }
  696.                     imagepng($dummy, $filename);
  697.                     imagedestroy($dummy);
  698.                 }
  699.                 else {
  700.                     imagepng($this->_img['main']['resource'], $filename);
  701.                 }
  702.                 break;
  703.                
  704.             default:
  705.                 trigger_error($this->_error_prefix . 'Output-Imagetype not supported.', E_USER_ERROR);
  706.                 return null;
  707.         }
  708.         return true;
  709.     }
  710.    
  711.     /**
  712.      * Sets the resize method of choice
  713.      *
  714.      * $method can be one of the following:<br>
  715.      * <ul>
  716.      * <li>'resize' -> supported by every version of GD (fast but ugly resize of image)</li>
  717.      * <li>'resample' -> only supported by GD version >= 2.0 (slower but antialiased resize of image)</li>
  718.      * <li>'workaround' -> supported by every version of GD (workaround function for bicubic resizing, downsizing, VERY slow!, taken from php.net comments)</li>
  719.      * <li>'workaround2' -> supported by every version of GD (alternative workaround function for bicubic resizing, down- and upsizing, VERY VERY slow!, taken from php.net comments)</li>
  720.      * </ul>
  721.      *
  722.      * @param string|integer $method resize method
  723.      * @return bool true on success, otherwise false
  724.      */
  725.     function setResizeMethod($method) {
  726.         switch ($method) {
  727.             case 1:
  728.             case '1':
  729.             case 'resize':
  730.                 $this->_resize_function = 'imagecopyresized';
  731.                 break;
  732.                
  733.             case 2:
  734.             case '2':
  735.             case 'resample':
  736.                 if (!function_exists('imagecopyresampled')) {
  737.                     // no error message. just return false.
  738.                     return null;
  739.                 }
  740.                 $this->_resize_function = 'imagecopyresampled';
  741.                 break;
  742.                
  743.             case 3:
  744.             case '3':
  745.             case 'resample_workaround':
  746.             case 'workaround':
  747.             case 'bicubic':
  748.                 $this->_resize_function = '$this->_imageCopyResampledWorkaround';
  749.                 break;
  750.                
  751.             case 4:
  752.             case '4':
  753.             case 'resample_workaround2':
  754.             case 'workaround2':
  755.             case 'bicubic2':
  756.                 $this->_resize_function = '$this->_imageCopyResampledWorkaround2';
  757.                 break;
  758.                
  759.             default:
  760.                 trigger_error($this->_error_prefix . 'Resizemethod not supported.', E_USER_ERROR);
  761.                 return null;
  762.         }
  763.         return true;
  764.     }
  765.    
  766.     /**
  767.      * Resize the current image
  768.      *
  769.      * if $width = 0 the new width will be calculated from the $height value preserving the correct aspectratio.<br>
  770.      *
  771.      * if $height = 0 the new height will be calculated from the $width value preserving the correct aspectratio.<br>
  772.      *
  773.      * $mode can be one of the following:<br>
  774.      * <ul>
  775.      * <li>0 -> image will be resized to the new output size, regardless of the original aspectratio. (default)</li>
  776.      * <li>1 -> image will be cropped if necessary to preserve the aspectratio and avoid image distortions.</li>
  777.      * <li>2 -> image will be resized preserving its original aspectratio. differences to the new outputsize will be filled with $bgcolor</li>
  778.      * </ul>
  779.      *
  780.      * if $autorotate is set to true the given $width and $height values may "change place" if the given image bias is different from the original one.<br>
  781.      * if either $width or $height is 0, the new size will be applied to either the new width or the new height based on the bias value of the original image.<br>
  782.      * (default = false)
  783.      *
  784.      * @param integer $width new width of image
  785.      * @param integer $height new height of image
  786.      * @param integer $mode resize mode
  787.      * @param bool $autorotate use autorotating
  788.      * @param string $bgcolor background fillcolor (hexformat, e.g. '#FF0000')
  789.      * @return bool true on success, otherwise false
  790.      */
  791.     function newOutputSize($width, $height, $mode = 0, $autorotate = false, $bgcolor = '#000000') {
  792.         if ($width > 0 && $height > 0 && is_int($width) && is_int($height)) {
  793.             //ignore aspectratio
  794.             if (!$mode) {
  795.                 //do not crop to get correct aspectratio
  796.                 ($width >= $height) ? ($this->_img['target']['bias'] = IMAGE_TOOLBOX_BIAS_HORIZONTAL) : ($this->_img['target']['bias'] = IMAGE_TOOLBOX_BIAS_VERTICAL);
  797.                 if ($this->_img['main']['bias'] == $this->_img['target']['bias'] || !$autorotate) {
  798.                     $this->_img['target']['width'] = $width;
  799.                     $this->_img['target']['height'] = $height;
  800.                 } else {
  801.                     $this->_img['target']['width'] = $height;
  802.                     $this->_img['target']['height'] = $width;
  803.                 }
  804.                 $this->_img['target']['aspectratio'] = $this->_img['target']['width'] / $this->_img['target']['height'];
  805.                
  806.                 $cpy_w = $this->_img['main']['width'];
  807.                 $cpy_h = $this->_img['main']['height'];
  808.                 $cpy_w_offset = 0;
  809.                 $cpy_h_offset = 0;
  810.             } elseif ($mode == 1) {
  811.                 //crop to get correct aspectratio
  812.                 ($width >= $height) ? ($this->_img['target']['bias'] = IMAGE_TOOLBOX_BIAS_HORIZONTAL) : ($this->_img['target']['bias'] = IMAGE_TOOLBOX_BIAS_VERTICAL);
  813.                 if ($this->_img['main']['bias'] == $this->_img['target']['bias'] || !$autorotate) {
  814.                     $this->_img['target']['width'] = $width;
  815.                     $this->_img['target']['height'] = $height;
  816.                 } else {
  817.                     $this->_img['target']['width'] = $height;
  818.                     $this->_img['target']['height'] = $width;
  819.                 }
  820.                 $this->_img['target']['aspectratio'] = $this->_img['target']['width'] / $this->_img['target']['height'];
  821.                
  822.                 if ($this->_img['main']['width'] / $this->_img['target']['width'] >= $this->_img['main']['height'] / $this->_img['target']['height']) {
  823.                     $cpy_h = $this->_img['main']['height'];
  824.                     $cpy_w = (integer) $this->_img['main']['height'] * $this->_img['target']['aspectratio'];
  825.                     $cpy_w_offset = (integer) ($this->_img['main']['width'] - $cpy_w) / 2;
  826.                     $cpy_h_offset = 0;
  827.                 } else {
  828.                     $cpy_w = $this->_img['main']['width'];
  829.                     $cpy_h = (integer) $this->_img['main']['width'] / $this->_img['target']['aspectratio'];
  830.                     $cpy_h_offset = (integer) ($this->_img['main']['height'] - $cpy_h) / 2;
  831.                     $cpy_w_offset = 0;
  832.                 }
  833.             }
  834.             elseif ($mode == 2) {
  835.                 //fill remaining background with a color to keep aspectratio
  836.                 $final_aspectratio = $width / $height;
  837.                 if ($final_aspectratio < $this->_img['main']['aspectratio']) {
  838.                     $this->_img['target']['width'] = $width;
  839.                     $this->_img['target']['height'] = (integer) $width / $this->_img['main']['aspectratio'];
  840.                     $cpy_w_offset2 = 0;
  841.                     $cpy_h_offset2 = (integer) (($height - $this->_img['target']['height']) / 2);
  842.                 }
  843.                 else {
  844.                     $this->_img['target']['height'] = $height;
  845.                     $this->_img['target']['width'] = (integer) $height * $this->_img['main']['aspectratio'];
  846.                     $cpy_h_offset2 = 0;
  847.                     $cpy_w_offset2 = (integer) (($width - $this->_img['target']['width']) / 2);
  848.                 }
  849.                 $this->_img['target']['aspectratio'] = $this->_img['main']['aspectratio'];
  850.                 $cpy_w = $this->_img['main']['width'];
  851.                 $cpy_h = $this->_img['main']['height'];
  852.                 $cpy_w_offset = 0;
  853.                 $cpy_h_offset = 0;
  854.             }
  855.         } elseif (($width == 0 && $height > 0) || ($width > 0 && $height == 0) && is_int($width) && is_int($height)) {
  856.             //keep aspectratio
  857.             if ($autorotate == true) {
  858.                 if ($this->_img['main']['bias'] == IMAGE_TOOLBOX_BIAS_HORIZONTAL && $width > 0) {
  859.                     $height = $width;
  860.                     $width = 0;
  861.                 } elseif ($this->_img['main']['bias'] == IMAGE_TOOLBOX_BIAS_VERTICAL && $height > 0) {
  862.                     $width = $height;
  863.                     $height = 0;
  864.                 }
  865.             }
  866.             ($width >= $height) ? ($this->_img['target']['bias'] = IMAGE_TOOLBOX_BIAS_HORIZONTAL) : ($this->_img['target']['bias'] = IMAGE_TOOLBOX_BIAS_VERTICAL);
  867.             if ($width != 0) {
  868.                 $this->_img['target']['width'] = $width;
  869.                 $this->_img['target']['height'] = (integer) $width / $this->_img['main']['aspectratio'];
  870.             } else {
  871.                 $this->_img['target']['height'] = $height;
  872.                 $this->_img['target']['width'] = (integer) $height * $this->_img['main']['aspectratio'];
  873.             }
  874.             $this->_img['target']['aspectratio'] = $this->_img['main']['aspectratio'];
  875.            
  876.             $cpy_w = $this->_img['main']['width'];
  877.             $cpy_h = $this->_img['main']['height'];
  878.             $cpy_w_offset = 0;
  879.             $cpy_h_offset = 0;
  880.         } else {
  881.             trigger_error($this->_error_prefix . 'Outputwidth and -height must be integers greater zero.', E_USER_ERROR);
  882.             return null;
  883.         }
  884.        
  885.         //create resized picture
  886.         $functionname = $this->_imagecreatefunction;
  887.         $dummy = $functionname($this->_img['target']['width'] + 1, $this->_img['target']['height'] + 1);
  888.         eval($this->_resize_function . '($dummy, $this->_img["main"]["resource"], 0, 0, $cpy_w_offset, $cpy_h_offset, $this->_img["target"]["width"], $this->_img["target"]["height"], $cpy_w, $cpy_h);');
  889.         if ($mode == 2) {
  890.             $this->_img['target']['resource'] = $functionname($width, $height);
  891.             $fillcolor = $this->_hexToPHPColor($bgcolor);
  892.             imagefill($this->_img['target']['resource'], 0, 0, $fillcolor);
  893.         } else {
  894.             $this->_img['target']['resource'] = $functionname($this->_img['target']['width'], $this->_img['target']['height']);
  895.             $cpy_w_offset2 = 0;
  896.             $cpy_h_offset2 = 0;
  897.         }
  898.         imagecopy($this->_img['target']['resource'], $dummy, $cpy_w_offset2, $cpy_h_offset2, 0, 0, $this->_img['target']['width'], $this->_img['target']['height']);
  899.         imagedestroy($dummy);
  900.        
  901.         if ($mode == 2) {
  902.             $this->_img['target']['width'] = $width;
  903.             $this->_img['target']['height'] = $height;
  904.         }
  905.         //update _img['main'] with new data
  906.         foreach ($this->_img['target'] as $key => $value) {
  907.             $this->_img['main'][$key] = $value;
  908.         }
  909.         unset ($this->_img['target']);
  910.        
  911.         return true;
  912.     }
  913.  
  914.     /**
  915.      * Adds a new image resource based on the given parameters.
  916.      *
  917.      * It does not overwrite the existing image resource.<br>
  918.      * Instead it is used to load a second image to merge with the existing image.
  919.      *
  920.      * Parameter:<br>
  921.      * <i>string</i> <b>$file</b> imagefile to load<br>
  922.      * Or:<br>
  923.      * <i>integer</i> <b>$width</b> imagewidth of new image to be created<br>
  924.      * <i>integer</i> <b>$height</b> imageheight of new image to be created<br>
  925.      * <i>string</i> <b>$fillcolor</b> optional fill the new image with this color (hexformat, e.g. '#FF0000')<br>
  926.      */
  927.     function addImage() {
  928.         $args = func_get_args();
  929.         $argc = func_num_args();
  930.        
  931.         if ($this->_addImage($argc, $args)) {
  932.             return true;
  933.         } else {
  934.             trigger_error($this->_error_prefix . 'failed to add image.', E_USER_ERROR);
  935.             return false;
  936.         }
  937.     }
  938.    
  939.     /**
  940.      * Blend two images.
  941.      *
  942.      * Original image and the image loaded with {@link addImage() addImage}<br>
  943.      * NOTE: This operation can take very long and is not intended for realtime use.
  944.      * (but of course depends on the power of your server :) )
  945.      *
  946.      * IMPORTANT: {@link imagecopymerge() imagecopymerged} doesn't work with PHP 4.3.2. Bug ID: {@link http://bugs.php.net/bug.php?id=24816 24816}<br>
  947.      *
  948.      * $x:<br>
  949.      * negative values are possible.<br>
  950.      * You can also use the following keywords ('left', 'center' or 'middle', 'right').<br>
  951.      * Additionally you can specify an offset in pixel with the keywords like this 'left +10'.<br>
  952.      * (default = 0)
  953.      *
  954.      * $y:<br>
  955.      * negative values are possible.<br>
  956.      * You can also use the following keywords ('top', 'center' or 'middle', 'bottom').<br>
  957.      * Additionally you can specify an offset in pixel with the keywords like this 'bottom -10'.<br>
  958.      * (default = 0)
  959.      *
  960.      * Possible values for $mode:
  961.      * <ul>
  962.      *  <li>IMAGE_TOOLBOX_BLEND_COPY</li>
  963.      *  <li>IMAGE_TOOLBOX_BLEND_MULTIPLY</li>
  964.      *  <li>IMAGE_TOOLBOX_BLEND_SCREEN</li>
  965.      *  <li>IMAGE_TOOLBOX_BLEND_DIFFERENCE</li>
  966.      *  <li>IMAGE_TOOLBOX_BLEND_EXCLUSION</li>
  967.      *  <li>IMAGE_TOOLBOX_BLEND_OVERLAY</li>
  968.      * </ul>
  969.      *
  970.      * $percent:<br>
  971.      * alpha value in percent of blend effect (0 - 100)<br>
  972.      * (default = 100)
  973.      *
  974.      * @param string|integer $x Horizontal position of second image.
  975.      * @param integer $y Vertical position of second image. negative values are possible.
  976.      * @param integer $mode blend mode.
  977.      * @param integer $percent alpha value
  978.      */
  979.     function blend($x = 0, $y = 0, $mode = IMAGE_TOOLBOX_BLEND_COPY, $percent = 100) {
  980.         if (is_string($x) || is_string($y)) {
  981.             list($xalign, $xalign_offset) = explode(" ", $x);
  982.             list($yalign, $yalign_offset) = explode(" ", $y);
  983.         }
  984.         if (is_string($x)) {
  985.             switch ($xalign) {
  986.                 case 'left':
  987.                     $dst_x = 0 + $xalign_offset;
  988.                     $src_x = 0;
  989.                     $src_w = $this->_img['operator']['width'];
  990.                     break;
  991.                    
  992.                 case 'right':
  993.                     $dst_x = ($this->_img['main']['width'] - $this->_img['operator']['width']) + $xalign_offset;
  994.                     $src_x = 0;
  995.                     $src_w = $this->_img['operator']['width'];
  996.                     break;
  997.                    
  998.                 case 'middle':
  999.                 case 'center':
  1000.                     $dst_x = (($this->_img['main']['width'] / 2) - ($this->_img['operator']['width'] / 2)) + $yalign_offset;
  1001.                     $src_x = 0;
  1002.                     $src_w = $this->_img['operator']['width'];
  1003.                     break;
  1004.             }
  1005.         } else {
  1006.             if ($x >= 0) {
  1007.                 $dst_x = $x;
  1008.                 $src_x = 0;
  1009.                 $src_w = $this->_img['operator']['width'];
  1010.             } else {
  1011.                 $dst_x = 0;
  1012.                 $src_x = abs($x);
  1013.                 $src_w = $this->_img['operator']['width'] - $src_x;
  1014.             }
  1015.         }
  1016.         if (is_string($y)) {
  1017.             switch ($yalign) {
  1018.                 case 'top':
  1019.                     $dst_y = 0 + $yalign_offset;
  1020.                     $src_y = 0;
  1021.                     $src_h = $this->_img['operator']['height'];
  1022.                     break;
  1023.                    
  1024.                 case 'bottom':
  1025.                     $dst_y = ($this->_img['main']['height'] - $this->_img['operator']['height']) + $yalign_offset;
  1026.                     $src_y = 0;
  1027.                     $src_h = $this->_img['operator']['height'];
  1028.                     break;
  1029.                    
  1030.                 case 'middle':
  1031.                 case 'center':
  1032.                     $dst_y = (($this->_img['main']['height'] / 2) - ($this->_img['operator']['height'] / 2)) + $yalign_offset;
  1033.                     $src_y = 0;
  1034.                     $src_h = $this->_img['operator']['height'];
  1035.                     break;
  1036.             }
  1037.         } else {
  1038.             if ($y >= 0) {
  1039.                 $dst_y = $y;
  1040.                 $src_y = 0;
  1041.                 $src_h = $this->_img['operator']['height'];
  1042.             } else {
  1043.                 $dst_y = 0;
  1044.                 $src_y = abs($y);
  1045.                 $src_h = $this->_img['operator']['height'] - $src_y;
  1046.             }
  1047.         }
  1048.         $this->_imageBlend($mode, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $percent);
  1049.         return true;
  1050.     }
  1051.    
  1052.     /**
  1053.      * Blend two images.
  1054.      *
  1055.      * @access private
  1056.      */
  1057.     function _imageBlend($mode, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $percent) {
  1058.         if ($mode == IMAGE_TOOLBOX_BLEND_COPY) {
  1059.             if ($percent == 100) {
  1060.                 imagecopy($this->_img['main']['resource'], $this->_img['operator']['resource'], $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
  1061.             } else {
  1062.                 imagecopymerge($this->_img['main']['resource'], $this->_img['operator']['resource'], $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $percent);
  1063.             }
  1064.         } else {
  1065.             $functionname = $this->_imagecreatefunction;
  1066.             $dummy = $functionname($src_w, $src_h);
  1067.             for ($y=0; $y < $src_h; $y++) {
  1068.                 for ($x=0; $x < $src_w; $x++) {
  1069.                     $colorindex = imagecolorat($this->_img['main']['resource'], $dst_x + $x, $dst_y + $y);
  1070.                     $colorrgb1 = imagecolorsforindex($this->_img['main']['resource'], $colorindex);
  1071.                     $colorindex = imagecolorat($this->_img['operator']['resource'], $src_x + $x, $src_y + $y);
  1072.                     $colorrgb2 = imagecolorsforindex($this->_img['operator']['resource'], $colorindex);
  1073.                     $colorblend = $this->_calculateBlendvalue($mode, $colorrgb1, $colorrgb2);
  1074.                     $newcolor = imagecolorallocate($dummy, $colorblend['red'], $colorblend['green'], $colorblend['blue']);
  1075.                     imagesetpixel($dummy, $x, $y, $newcolor);
  1076.                 }
  1077.             }
  1078.        
  1079.             $this->_img['target']['resource'] = $functionname($this->_img['main']['width'], $this->_img['main']['height']);
  1080.             imagecopy($this->_img['target']['resource'], $this->_img['main']['resource'], 0, 0, 0, 0, $this->_img['main']['width'], $this->_img['main']['height']);
  1081.             imagecopymerge($this->_img['target']['resource'], $dummy, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $percent);
  1082.                                    
  1083.             $this->_img['main']['resource'] = $this->_img['target']['resource'];
  1084.             unset($this->_img['target']);
  1085.         }
  1086.     }
  1087.    
  1088.     /**
  1089.      * Calculate blend values for given blend mode
  1090.      *
  1091.      * @access private
  1092.      */
  1093.     function _calculateBlendvalue($mode, $colorrgb1, $colorrgb2) {
  1094.         switch ($mode) {
  1095.             case IMAGE_TOOLBOX_BLEND_MULTIPLY:
  1096.                 $c['red'] = ($colorrgb1['red'] * $colorrgb2['red']) >> 8;
  1097.                 $c['green'] = ($colorrgb1['green'] * $colorrgb2['green']) >> 8;
  1098.                 $c['blue'] = ($colorrgb1['blue'] * $colorrgb2['blue']) >> 8;
  1099.                 break;
  1100.            
  1101.             case IMAGE_TOOLBOX_BLEND_SCREEN:
  1102.                 $c['red'] = 255 - ((255 - $colorrgb1['red']) * (255 - $colorrgb2['red']) >> 8);
  1103.                 $c['green'] = 255 - ((255 - $colorrgb1['green']) * (255 - $colorrgb2['green']) >> 8);
  1104.                 $c['blue'] = 255 - ((255 - $colorrgb1['blue']) * (255 - $colorrgb2['blue']) >> 8);
  1105.                 break;
  1106.            
  1107.             case IMAGE_TOOLBOX_BLEND_DIFFERENCE:
  1108.                 $c['red'] = abs($colorrgb1['red'] - $colorrgb2['red']);
  1109.                 $c['green'] = abs($colorrgb1['green'] - $colorrgb2['green']);
  1110.                 $c['blue'] = abs($colorrgb1['blue'] - $colorrgb2['blue']);
  1111.                 break;
  1112.            
  1113.             case IMAGE_TOOLBOX_BLEND_NEGATION: 
  1114.                 $c['red'] = 255 - abs(255 - $colorrgb1['red'] - $colorrgb2['red']);
  1115.                 $c['green'] = 255 - abs(255 - $colorrgb1['green'] - $colorrgb2['green']);
  1116.                 $c['blue'] = 255 - abs(255 - $colorrgb1['blue'] - $colorrgb2['blue']);
  1117.                 break;
  1118.                
  1119.             case IMAGE_TOOLBOX_BLEND_EXCLUTION:
  1120.                 $c['red'] = $colorrgb1['red'] + $colorrgb2['red'] - (($colorrgb1['red'] * $colorrgb2['red']) >> 7);
  1121.                 $c['green'] = $colorrgb1['green'] + $colorrgb2['green'] - (($colorrgb1['green'] * $colorrgb2['green']) >> 7);
  1122.                 $c['blue'] = $colorrgb1['blue'] + $colorrgb2['blue'] - (($colorrgb1['blue'] * $colorrgb2['blue']) >> 7);
  1123.                 break;
  1124.                
  1125.             case IMAGE_TOOLBOX_BLEND_OVERLAY:          
  1126.                 if ($colorrgb1['red'] < 128) {
  1127.                     $c['red']= ($colorrgb1['red'] * $colorrgb2['red']) >> 7;
  1128.                 } else {
  1129.                     $c['red'] = 255 - ((255 - $colorrgb1['red']) * (255 - $colorrgb2['red']) >> 7);
  1130.                 }
  1131.                 if ($colorrgb1['green'] < 128) {
  1132.                     $c['green'] = ($colorrgb1['green'] * $colorrgb2['green']) >> 7;
  1133.                 } else {
  1134.                     $c['green'] = 255 - ((255 - $colorrgb1['green']) * (255 - $colorrgb2['green']) >> 7);
  1135.                 }
  1136.                 if ($colorrgb1['blue'] < 128) {
  1137.                     $c['blue'] = ($colorrgb1['blue'] * $colorrgb2['blue']) >> 7;
  1138.                 } else {
  1139.                     $c['blue'] = 255 - ((255 - $colorrgb1['blue']) * (255 - $colorrgb2['blue']) >> 7);
  1140.                 }
  1141.                 break;
  1142.                
  1143.             default:
  1144.                 break;
  1145.         }
  1146.         return $c;
  1147.     }
  1148.    
  1149.     /**
  1150.      * convert iso character coding to unicode (PHP conform)
  1151.      * needed for TTF text generation of special characters (Latin-2)
  1152.      *
  1153.      * @access private
  1154.      */
  1155.     function _iso2uni($isoline) {
  1156.         $iso2uni = array(
  1157.             173 => "&#161;",
  1158.             155 => "&#162;",
  1159.             156 => "&#163;",
  1160.             15 => "&#164;",
  1161.             157 => "&#165;",
  1162.             124 => "&#166;",
  1163.             21 => "&#167;",
  1164.             249 => "&#168;",
  1165.             184 => "&#169;",
  1166.             166 => "&#170;",
  1167.             174 => "&#171;",
  1168.             170 => "&#172;",
  1169.             169 => "&#174;",
  1170.             238 => "&#175;",
  1171.             248 => "&#176;",
  1172.             241 => "&#177;",
  1173.             253 => "&#178;",
  1174.             252 => "&#179;",
  1175.             239 => "&#180;",
  1176.             230 => "&#181;",
  1177.             20 => "&#182;",
  1178.             250 => "&#183;",
  1179.             247 => "&#184;",
  1180.             251 => "&#185;",
  1181.             167 => "&#186;",
  1182.             175 => "&#187;",
  1183.             172 => "&#188;",
  1184.             171 => "&#189;",
  1185.             243 => "&#190;",
  1186.             168 => "&#191;",
  1187.             183 => "&#192;",
  1188.             181 => "&#193;",
  1189.             182 => "&#194;",
  1190.             199 => "&#195;",
  1191.             142 => "&#196;",
  1192.             143 => "&#197;",
  1193.             146 => "&#198;",
  1194.             128 => "&#199;",
  1195.             212 => "&#200;",
  1196.             144 => "&#201;",
  1197.             210 => "&#202;",
  1198.             211 => "&#203;",
  1199.             141 => "&#204;",
  1200.             161 => "&#205;",
  1201.             140 => "&#206;",
  1202.             139 => "&#207;",
  1203.             209 => "&#208;",
  1204.             165 => "&#209;",
  1205.             227 => "&#210;",
  1206.             224 => "&#211;",
  1207.             226 => "&#212;",
  1208.             229 => "&#213;",
  1209.             153 => "&#214;",
  1210.             158 => "&#215;",
  1211.             157 => "&#216;",
  1212.             235 => "&#217;",
  1213.             233 => "&#218;",
  1214.             234 => "&#219;",
  1215.             154 => "&#220;",
  1216.             237 => "&#221;",
  1217.             232 => "&#222;",
  1218.             225 => "&#223;",
  1219.             133 => "&#224;",
  1220.             160 => "&#225;",
  1221.             131 => "&#226;",
  1222.             198 => "&#227;",
  1223.             132 => "&#228;",
  1224.             134 => "&#229;",
  1225.             145 => "&#230;",
  1226.             135 => "&#231;",
  1227.             138 => "&#232;",
  1228.             130 => "&#233;",
  1229.             136 => "&#234;",
  1230.             137 => "&#235;",
  1231.             141 => "&#236;",
  1232.             161 => "&#237;",
  1233.             140 => "&#238;",
  1234.             139 => "&#239;",
  1235.             208 => "&#240;",
  1236.             164 => "&#241;",
  1237.             149 => "&#242;",
  1238.             162 => "&#243;",
  1239.             147 => "&#244;",
  1240.             228 => "&#245;",
  1241.             148 => "&#246;",
  1242.             246 => "&#247;",
  1243.             155 => "&#248;",
  1244.             151 => "&#249;",
  1245.             163 => "&#250;",
  1246.             150 => "&#251;",
  1247.             129 => "&#252;",
  1248.             236 => "&#253;",
  1249.             231 => "&#254;",
  1250.             152 => "&#255;"
  1251.         );
  1252.         for ($i=0; $i < strlen($isoline); $i++){
  1253.             $thischar = substr($isoline, $i, 1);
  1254.             $new = $iso2uni[ord($thischar)];
  1255.             $uniline .= ($new != "") ? $new : $thischar;
  1256.         }
  1257.         return $uniline;
  1258.     }
  1259.  
  1260.     /**
  1261.      * Writes text over the image
  1262.      *
  1263.      * only TTF fonts are supported at the moment
  1264.      *
  1265.      * $x:<br>
  1266.      * You can also use the following keywords ('left', 'center' or 'middle', 'right').<br>
  1267.      * Additionally you can specify an offset in pixel with the keywords like this 'left +10'.<br>
  1268.      * (default = 0)
  1269.      *
  1270.      * $y:<br>
  1271.      * You can also use the following keywords ('top', 'center' or 'middle', 'bottom').<br>
  1272.      * Additionally you can specify an offset in pixel with the keywords like this 'bottom -10'.<br>
  1273.      * (default = 0)
  1274.      *
  1275.      * @param string $text text to be generated.
  1276.      * @param string $font TTF fontfile to be used. (relative paths are ok).
  1277.      * @param integer $size textsize.
  1278.      * @param string $color textcolor in hexformat (e.g. '#FF0000').
  1279.      * @param string|integer $x horizontal postion in pixel.
  1280.      * @param string|integer $y vertical postion in pixel.
  1281.      * @param integer $angle rotation of the text.
  1282.      */
  1283.     function addText($text, $font, $size, $color, $x, $y, $angle = 0) {
  1284.         global $HTTP_SERVER_VARS;
  1285.        
  1286.         if (substr($font, 0, 1) == DIRECTORY_SEPARATOR || (substr($font, 1, 1) == ":" && (substr($font, 2, 1) == "\\" || substr($font, 2, 1) == "/"))) {
  1287.             $prepath = '';
  1288.         } else {
  1289.             $prepath = substr($HTTP_SERVER_VARS['SCRIPT_FILENAME'], 0, strrpos($HTTP_SERVER_VARS['SCRIPT_FILENAME'], DIRECTORY_SEPARATOR)) . DIRECTORY_SEPARATOR;
  1290.         }
  1291.         $text = $this->_iso2uni($text);
  1292.         if (is_string($x) || is_string($y)) {
  1293.             $textsize = imagettfbbox($size, $angle, $prepath.$font, $text);
  1294.             $textwidth = abs($textsize[2]);
  1295.             $textheight = abs($textsize[7]);
  1296.             list($xalign, $xalign_offset) = explode(" ", $x);
  1297.             list($yalign, $yalign_offset) = explode(" ", $y);
  1298.         }
  1299.         if (is_string($x)) {
  1300.             switch ($xalign) {
  1301.                 case 'left':
  1302.                     $x = 0 + $xalign_offset;
  1303.                     break;
  1304.                    
  1305.                 case 'right':
  1306.                     $x = ($this->_img['main']['width'] - $textwidth) + $xalign_offset;
  1307.                     break;
  1308.                    
  1309.                 case 'middle':
  1310.                 case 'center':
  1311.                     $x = (($this->_img['main']['width'] - $textwidth) / 2) + $xalign_offset;
  1312.                     break;
  1313.             }
  1314.         }
  1315.         if (is_string($y)) {
  1316.             switch ($yalign) {
  1317.                 case 'top':
  1318.                     $y = (0 + $textheight) + $yalign_offset;
  1319.                     break;
  1320.                    
  1321.                 case 'bottom':
  1322.                     $y = ($this->_img['main']['height']) + $yalign_offset;
  1323.                     break;
  1324.                    
  1325.                 case 'middle':
  1326.                 case 'center':
  1327.                     $y = ((($this->_img['main']['height'] - $textheight) / 2) + $textheight) + $yalign_offset;
  1328.                     break;
  1329.             }
  1330.         }
  1331.         imagettftext($this->_img['main']['resource'], $size, $angle, $x, $y, $this->_hexToPHPColor($color), $prepath . $font, $text);
  1332.         return true;
  1333.     }
  1334.    
  1335.     /**
  1336.      * workaround function for bicubic resizing. works well for downsizing only. VERY slow. taken from php.net comments
  1337.      *
  1338.      * @access private
  1339.      */
  1340.     function _imageCopyResampledWorkaround(&$dst_img, &$src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
  1341.         /*
  1342.         for ($i = 0; $i < imagecolorstotal($src_img); $i++)
  1343.         {
  1344.             $colors = ImageColorsForIndex ($src_img, $i);
  1345.             ImageColorAllocate ($dst_img, $colors['red'],$colors['green'], $colors['blue']);
  1346.         }
  1347.         */
  1348.         $scaleX = ($src_w - 1) / $dst_w;
  1349.         $scaleY = ($src_h - 1) / $dst_h;
  1350.  
  1351.         $scaleX2 = $scaleX / 2.0;
  1352.         $scaleY2 = $scaleY / 2.0;
  1353.  
  1354.         for ($j = $src_y; $j < $src_y + $dst_h; $j++) {
  1355.             $sY = $j * $scaleY;
  1356.             for ($i = $src_x; $i < $src_x + $dst_w; $i++) {
  1357.                 $sX = $i * $scaleX;
  1358.  
  1359.                 $c1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, (int) $sX, (int) $sY + $scaleY2));
  1360.                 $c2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, (int) $sX, (int) $sY));
  1361.                 $c3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, (int) $sX + $scaleX2, (int) $sY + $scaleY2));
  1362.                 $c4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, (int) $sX + $scaleX2, (int) $sY));
  1363.  
  1364.                 $red = (integer) (($c1['red'] + $c2['red'] + $c3['red'] + $c4['red']) / 4);
  1365.                 $green = (integer) (($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) / 4);
  1366.                 $blue = (integer) (($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue']) / 4);
  1367.  
  1368.                 $color = ImageColorClosest ($dst_img, $red, $green,$blue);
  1369.                 ImageSetPixel ($dst_img, $dst_x + $i - $src_x, $dst_y + $j - $src_y,$color);
  1370.             }
  1371.         }
  1372.     }
  1373.  
  1374.     /**
  1375.      * alternative workaround function for bicubic resizing. works well for downsizing and upsizing. VERY VERY slow. taken from php.net comments
  1376.      *
  1377.      * @access private
  1378.      */
  1379.     function _imageCopyResampledWorkaround2(&$dst_img, &$src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
  1380.         ImagePaletteCopy ($dst_img, $src_img);
  1381.         $rX = $src_w / $dst_w;
  1382.         $rY = $src_h / $dst_h;
  1383.         $w = 0;
  1384.         for ($y = $dst_y; $y < $dst_h; $y++) {
  1385.             $ow = $w; $w = round(($y + 1) * $rY);
  1386.             $t = 0;
  1387.             for ($x = $dst_x; $x < $dst_w; $x++) {
  1388.                 $r = $g = $b = 0; $a = 0;
  1389.                 $ot = $t; $t = round(($x + 1) * $rX);
  1390.                 for ($u = 0; $u < ($w - $ow); $u++) {
  1391.                     for ($p = 0; $p < ($t - $ot); $p++) {
  1392.                         $c = ImageColorsForIndex ($src_img, ImageColorAt ($src_img, $ot + $p, $ow + $u));
  1393.                         $r += $c['red'];
  1394.                         $g += $c['green'];
  1395.                         $b += $c['blue'];
  1396.                         $a++;
  1397.                     }
  1398.                 }
  1399.                 ImageSetPixel ($dst_img, $x, $y, ImageColorClosest ($dst_img, $r / $a, $g / $a, $b / $a));
  1400.             }
  1401.         }
  1402.     }
  1403. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement