firestorm_dev

class.upload.php

May 17th, 2017
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 245.78 KB | None | 0 0
  1. <?php
  2. // +------------------------------------------------------------------------+
  3. // | class.upload.php                                                       |
  4. // +------------------------------------------------------------------------+
  5. // | Copyright (c) Colin Verot 2003-2014. All rights reserved.              |
  6. // | Email         colin@verot.net                                          |
  7. // | Web           http://www.verot.net                                     |
  8. // +------------------------------------------------------------------------+
  9. // | This program is free software; you can redistribute it and/or modify   |
  10. // | it under the terms of the GNU General Public License version 2 as      |
  11. // | published by the Free Software Foundation.                             |
  12. // |                                                                        |
  13. // | This program is distributed in the hope that it will be useful,        |
  14. // | but WITHOUT ANY WARRANTY; without even the implied warranty of         |
  15. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          |
  16. // | GNU General Public License for more details.                           |
  17. // |                                                                        |
  18. // | You should have received a copy of the GNU General Public License      |
  19. // | along with this program; if not, write to the                          |
  20. // |   Free Software Foundation, Inc., 59 Temple Place, Suite 330,          |
  21. // |   Boston, MA 02111-1307 USA                                            |
  22. // |                                                                        |
  23. // | Please give credit on sites that use class.upload and submit changes   |
  24. // | of the script so other people can use them as well.                    |
  25. // | This script is free to use, don't abuse.                               |
  26. // +------------------------------------------------------------------------+
  27.  
  28.  
  29. /**
  30.  * Class upload
  31.  *
  32.  * @author    Colin Verot <colin@verot.net>
  33.  * @license   http://opensource.org/licenses/gpl-license.php GNU Public License
  34.  * @copyright Colin Verot
  35.  */
  36. class upload {
  37.  
  38.  
  39.     /**
  40.      * Class version
  41.      *
  42.      * @access public
  43.      * @var string
  44.      */
  45.     var $version;
  46.  
  47.     /**
  48.      * Uploaded file name
  49.      *
  50.      * @access public
  51.      * @var string
  52.      */
  53.     var $file_src_name;
  54.  
  55.     /**
  56.      * Uploaded file name body (i.e. without extension)
  57.      *
  58.      * @access public
  59.      * @var string
  60.      */
  61.     var $file_src_name_body;
  62.  
  63.     /**
  64.      * Uploaded file name extension
  65.      *
  66.      * @access public
  67.      * @var string
  68.      */
  69.     var $file_src_name_ext;
  70.  
  71.     /**
  72.      * Uploaded file MIME type
  73.      *
  74.      * @access public
  75.      * @var string
  76.      */
  77.     var $file_src_mime;
  78.  
  79.     /**
  80.      * Uploaded file size, in bytes
  81.      *
  82.      * @access public
  83.      * @var double
  84.      */
  85.     var $file_src_size;
  86.  
  87.     /**
  88.      * Holds eventual PHP error code from $_FILES
  89.      *
  90.      * @access public
  91.      * @var string
  92.      */
  93.     var $file_src_error;
  94.  
  95.     /**
  96.      * Uloaded file name, including server path
  97.      *
  98.      * @access public
  99.      * @var string
  100.      */
  101.     var $file_src_pathname;
  102.  
  103.     /**
  104.      * Uloaded file name temporary copy
  105.      *
  106.      * @access private
  107.      * @var string
  108.      */
  109.     var $file_src_temp;
  110.  
  111.     /**
  112.      * Destination file name
  113.      *
  114.      * @access public
  115.      * @var string
  116.      */
  117.     var $file_dst_path;
  118.  
  119.     /**
  120.      * Destination file name
  121.      *
  122.      * @access public
  123.      * @var string
  124.      */
  125.     var $file_dst_name;
  126.  
  127.     /**
  128.      * Destination file name body (i.e. without extension)
  129.      *
  130.      * @access public
  131.      * @var string
  132.      */
  133.     var $file_dst_name_body;
  134.  
  135.     /**
  136.      * Destination file extension
  137.      *
  138.      * @access public
  139.      * @var string
  140.      */
  141.     var $file_dst_name_ext;
  142.  
  143.     /**
  144.      * Destination file name, including path
  145.      *
  146.      * @access public
  147.      * @var string
  148.      */
  149.     var $file_dst_pathname;
  150.  
  151.     /**
  152.      * Source image width
  153.      *
  154.      * @access public
  155.      * @var integer
  156.      */
  157.     var $image_src_x;
  158.  
  159.     /**
  160.      * Source image height
  161.      *
  162.      * @access public
  163.      * @var integer
  164.      */
  165.     var $image_src_y;
  166.  
  167.     /**
  168.      * Source image color depth
  169.      *
  170.      * @access public
  171.      * @var integer
  172.      */
  173.     var $image_src_bits;
  174.  
  175.     /**
  176.      * Number of pixels
  177.      *
  178.      * @access public
  179.      * @var long
  180.      */
  181.     var $image_src_pixels;
  182.  
  183.     /**
  184.      * Type of image (png, gif, jpg or bmp)
  185.      *
  186.      * @access public
  187.      * @var string
  188.      */
  189.     var $image_src_type;
  190.  
  191.     /**
  192.      * Destination image width
  193.      *
  194.      * @access public
  195.      * @var integer
  196.      */
  197.     var $image_dst_x;
  198.  
  199.     /**
  200.      * Destination image height
  201.      *
  202.      * @access public
  203.      * @var integer
  204.      */
  205.     var $image_dst_y;
  206.  
  207.     /**
  208.      * Destination image type (png, gif, jpg or bmp)
  209.      *
  210.      * @access public
  211.      * @var integer
  212.      */
  213.     var $image_dst_type;
  214.  
  215.     /**
  216.      * Supported image formats
  217.      *
  218.      * @access private
  219.      * @var array
  220.      */
  221.     var $image_supported;
  222.  
  223.     /**
  224.      * Flag to determine if the source file is an image
  225.      *
  226.      * @access public
  227.      * @var boolean
  228.      */
  229.     var $file_is_image;
  230.  
  231.     /**
  232.      * Flag set after instanciating the class
  233.      *
  234.      * Indicates if the file has been uploaded properly
  235.      *
  236.      * @access public
  237.      * @var bool
  238.      */
  239.     var $uploaded;
  240.  
  241.     /**
  242.      * Flag stopping PHP upload checks
  243.      *
  244.      * Indicates whether we instanciated the class with a filename, in which case
  245.      * we will not check on the validity of the PHP *upload*
  246.      *
  247.      * This flag is automatically set to true when working on a local file
  248.      *
  249.      * Warning: for uploads, this flag MUST be set to false for security reason
  250.      *
  251.      * @access public
  252.      * @var bool
  253.      */
  254.     var $no_upload_check;
  255.  
  256.     /**
  257.      * Flag set after calling a process
  258.      *
  259.      * Indicates if the processing, and copy of the resulting file went OK
  260.      *
  261.      * @access public
  262.      * @var bool
  263.      */
  264.     var $processed;
  265.  
  266.     /**
  267.      * Holds eventual error message in plain english
  268.      *
  269.      * @access public
  270.      * @var string
  271.      */
  272.     var $error;
  273.  
  274.     /**
  275.      * Holds an HTML formatted log
  276.      *
  277.      * @access public
  278.      * @var string
  279.      */
  280.     var $log;
  281.  
  282.  
  283.     // overiddable processing variables
  284.  
  285.  
  286.     /**
  287.      * Set this variable to replace the name body (i.e. without extension)
  288.      *
  289.      * @access public
  290.      * @var string
  291.      */
  292.     var $file_new_name_body;
  293.  
  294.     /**
  295.      * Set this variable to append a string to the file name body
  296.      *
  297.      * @access public
  298.      * @var string
  299.      */
  300.     var $file_name_body_add;
  301.  
  302.     /**
  303.      * Set this variable to prepend a string to the file name body
  304.      *
  305.      * @access public
  306.      * @var string
  307.      */
  308.     var $file_name_body_pre;
  309.  
  310.     /**
  311.      * Set this variable to change the file extension
  312.      *
  313.      * @access public
  314.      * @var string
  315.      */
  316.     var $file_new_name_ext;
  317.  
  318.     /**
  319.      * Set this variable to format the filename (spaces changed to _)
  320.      *
  321.      * @access public
  322.      * @var boolean
  323.      */
  324.     var $file_safe_name;
  325.  
  326.     /**
  327.      * Forces an extension if the source file doesn't have one
  328.      *
  329.      * If the file is an image, then the correct extension will be added
  330.      * Otherwise, a .txt extension will be chosen
  331.      *
  332.      * @access public
  333.      * @var boolean
  334.      */
  335.     var $file_force_extension;
  336.  
  337.     /**
  338.      * Set this variable to false if you don't want to check the MIME against the allowed list
  339.      *
  340.      * This variable is set to true by default for security reason
  341.      *
  342.      * @access public
  343.      * @var boolean
  344.      */
  345.     var $mime_check;
  346.  
  347.     /**
  348.      * Set this variable to false in the init() function if you don't want to check the MIME
  349.      * with Fileinfo PECL extension. On some systems, Fileinfo is known to be buggy, and you
  350.      * may want to deactivate it in the class code directly.
  351.      *
  352.      * You can also set it with the path of the magic database file.
  353.      * If set to true, the class will try to read the MAGIC environment variable
  354.      *   and if it is empty, will default to the system's default
  355.      * If set to an empty string, it will call finfo_open without the path argument
  356.      *
  357.      * This variable is set to true by default for security reason
  358.      *
  359.      * @access public
  360.      * @var boolean
  361.      */
  362.     var $mime_fileinfo;
  363.  
  364.     /**
  365.      * Set this variable to false in the init() function if you don't want to check the MIME
  366.      * with UNIX file() command
  367.      *
  368.      * This variable is set to true by default for security reason
  369.      *
  370.      * @access public
  371.      * @var boolean
  372.      */
  373.     var $mime_file;
  374.  
  375.     /**
  376.      * Set this variable to false in the init() function if you don't want to check the MIME
  377.      * with the magic.mime file
  378.      *
  379.      * The function mime_content_type() will be deprecated,
  380.      * and this variable will be set to false in a future release
  381.      *
  382.      * This variable is set to true by default for security reason
  383.      *
  384.      * @access public
  385.      * @var boolean
  386.      */
  387.     var $mime_magic;
  388.  
  389.     /**
  390.      * Set this variable to false in the init() function if you don't want to check the MIME
  391.      * with getimagesize()
  392.      *
  393.      * The class tries to get a MIME type from getimagesize()
  394.      * If no MIME is returned, it tries to guess the MIME type from the file type
  395.      *
  396.      * This variable is set to true by default for security reason
  397.      *
  398.      * @access public
  399.      * @var boolean
  400.      */
  401.     var $mime_getimagesize;
  402.  
  403.     /**
  404.      * Set this variable to false if you don't want to turn dangerous scripts into simple text files
  405.      *
  406.      * @access public
  407.      * @var boolean
  408.      */
  409.     var $no_script;
  410.  
  411.     /**
  412.      * Set this variable to true to allow automatic renaming of the file
  413.      * if the file already exists
  414.      *
  415.      * Default value is true
  416.      *
  417.      * For instance, on uploading foo.ext,<br>
  418.      * if foo.ext already exists, upload will be renamed foo_1.ext<br>
  419.      * and if foo_1.ext already exists, upload will be renamed foo_2.ext<br>
  420.      *
  421.      * Note that this option doesn't have any effect if {@link file_overwrite} is true
  422.      *
  423.      * @access public
  424.      * @var bool
  425.      */
  426.     var $file_auto_rename;
  427.  
  428.     /**
  429.      * Set this variable to true to allow automatic creation of the destination
  430.      * directory if it is missing (works recursively)
  431.      *
  432.      * Default value is true
  433.      *
  434.      * @access public
  435.      * @var bool
  436.      */
  437.     var $dir_auto_create;
  438.  
  439.     /**
  440.      * Set this variable to true to allow automatic chmod of the destination
  441.      * directory if it is not writeable
  442.      *
  443.      * Default value is true
  444.      *
  445.      * @access public
  446.      * @var bool
  447.      */
  448.     var $dir_auto_chmod;
  449.  
  450.     /**
  451.      * Set this variable to the default chmod you want the class to use
  452.      * when creating directories, or attempting to write in a directory
  453.      *
  454.      * Default value is 0777 (without quotes)
  455.      *
  456.      * @access public
  457.      * @var bool
  458.      */
  459.     var $dir_chmod;
  460.  
  461.     /**
  462.      * Set this variable tu true to allow overwriting of an existing file
  463.      *
  464.      * Default value is false, so no files will be overwritten
  465.      *
  466.      * @access public
  467.      * @var bool
  468.      */
  469.     var $file_overwrite;
  470.  
  471.     /**
  472.      * Set this variable to change the maximum size in bytes for an uploaded file
  473.      *
  474.      * Default value is the value <i>upload_max_filesize</i> from php.ini
  475.      *
  476.      * Value in bytes (integer) or shorthand byte values (string) is allowed.
  477.      * The available options are K (for Kilobytes), M (for Megabytes) and G (for Gigabytes)
  478.      *
  479.      * @access public
  480.      * @var double
  481.      */
  482.     var $file_max_size;
  483.  
  484.     /**
  485.      * Set this variable to true to resize the file if it is an image
  486.      *
  487.      * You will probably want to set {@link image_x} and {@link image_y}, and maybe one of the ratio variables
  488.      *
  489.      * Default value is false (no resizing)
  490.      *
  491.      * @access public
  492.      * @var bool
  493.      */
  494.     var $image_resize;
  495.  
  496.     /**
  497.      * Set this variable to convert the file if it is an image
  498.      *
  499.      * Possibles values are : ''; 'png'; 'jpeg'; 'gif'; 'bmp'
  500.      *
  501.      * Default value is '' (no conversion)<br>
  502.      * If {@link resize} is true, {@link convert} will be set to the source file extension
  503.      *
  504.      * @access public
  505.      * @var string
  506.      */
  507.     var $image_convert;
  508.  
  509.     /**
  510.      * Set this variable to the wanted (or maximum/minimum) width for the processed image, in pixels
  511.      *
  512.      * Default value is 150
  513.      *
  514.      * @access public
  515.      * @var integer
  516.      */
  517.     var $image_x;
  518.  
  519.     /**
  520.      * Set this variable to the wanted (or maximum/minimum) height for the processed image, in pixels
  521.      *
  522.      * Default value is 150
  523.      *
  524.      * @access public
  525.      * @var integer
  526.      */
  527.     var $image_y;
  528.  
  529.     /**
  530.      * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}
  531.      *
  532.      * Default value is false
  533.      *
  534.      * @access public
  535.      * @var bool
  536.      */
  537.     var $image_ratio;
  538.  
  539.     /**
  540.      * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}
  541.      *
  542.      * The image will be resized as to fill the whole space, and excedent will be cropped
  543.      *
  544.      * Value can also be a string, one or more character from 'TBLR' (top, bottom, left and right)
  545.      * If set as a string, it determines which side of the image is kept while cropping.
  546.      * By default, the part of the image kept is in the center, i.e. it crops equally on both sides
  547.      *
  548.      * Default value is false
  549.      *
  550.      * @access public
  551.      * @var mixed
  552.      */
  553.     var $image_ratio_crop;
  554.  
  555.     /**
  556.      * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}
  557.      *
  558.      * The image will be resized to fit entirely in the space, and the rest will be colored.
  559.      * The default color is white, but can be set with {@link image_default_color}
  560.      *
  561.      * Value can also be a string, one or more character from 'TBLR' (top, bottom, left and right)
  562.      * If set as a string, it determines in which side of the space the image is displayed.
  563.      * By default, the image is displayed in the center, i.e. it fills the remaining space equally on both sides
  564.      *
  565.      * Default value is false
  566.      *
  567.      * @access public
  568.      * @var mixed
  569.      */
  570.     var $image_ratio_fill;
  571.  
  572.     /**
  573.      * Set this variable to a number of pixels so that {@link image_x} and {@link image_y} are the best match possible
  574.      *
  575.      * The image will be resized to have approximatively the number of pixels
  576.      * The aspect ratio wil be conserved
  577.      *
  578.      * Default value is false
  579.      *
  580.      * @access public
  581.      * @var mixed
  582.      */
  583.     var $image_ratio_pixels;
  584.  
  585.     /**
  586.      * Set this variable to calculate {@link image_x} automatically , using {@link image_y} and conserving ratio
  587.      *
  588.      * Default value is false
  589.      *
  590.      * @access public
  591.      * @var bool
  592.      */
  593.     var $image_ratio_x;
  594.  
  595.     /**
  596.      * Set this variable to calculate {@link image_y} automatically , using {@link image_x} and conserving ratio
  597.      *
  598.      * Default value is false
  599.      *
  600.      * @access public
  601.      * @var bool
  602.      */
  603.     var $image_ratio_y;
  604.  
  605.     /**
  606.      * (deprecated) Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y},
  607.      * but only if original image is bigger
  608.      *
  609.      * This setting is soon to be deprecated. Instead, use {@link image_ratio} and {@link image_no_enlarging}
  610.      *
  611.      * Default value is false
  612.      *
  613.      * @access public
  614.      * @var bool
  615.      */
  616.     var $image_ratio_no_zoom_in;
  617.  
  618.     /**
  619.      * (deprecated) Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y},
  620.      * but only if original image is smaller
  621.      *
  622.      * Default value is false
  623.      *
  624.      * This setting is soon to be deprecated. Instead, use {@link image_ratio} and {@link image_no_shrinking}
  625.      *
  626.      * @access public
  627.      * @var bool
  628.      */
  629.     var $image_ratio_no_zoom_out;
  630.  
  631.     /**
  632.      * Cancel resizing if the resized image is bigger than the original image, to prevent enlarging
  633.      *
  634.      * Default value is false
  635.      *
  636.      * @access public
  637.      * @var bool
  638.      */
  639.     var $image_no_enlarging;
  640.  
  641.     /**
  642.      * Cancel resizing if the resized image is smaller than the original image, to prevent shrinking
  643.      *
  644.      * Default value is false
  645.      *
  646.      * @access public
  647.      * @var bool
  648.      */
  649.     var $image_no_shrinking;
  650.  
  651.     /**
  652.      * Set this variable to set a maximum image width, above which the upload will be invalid
  653.      *
  654.      * Default value is null
  655.      *
  656.      * @access public
  657.      * @var integer
  658.      */
  659.     var $image_max_width;
  660.  
  661.     /**
  662.      * Set this variable to set a maximum image height, above which the upload will be invalid
  663.      *
  664.      * Default value is null
  665.      *
  666.      * @access public
  667.      * @var integer
  668.      */
  669.     var $image_max_height;
  670.  
  671.     /**
  672.      * Set this variable to set a maximum number of pixels for an image, above which the upload will be invalid
  673.      *
  674.      * Default value is null
  675.      *
  676.      * @access public
  677.      * @var long
  678.      */
  679.     var $image_max_pixels;
  680.  
  681.     /**
  682.      * Set this variable to set a maximum image aspect ratio, above which the upload will be invalid
  683.      *
  684.      * Note that ratio = width / height
  685.      *
  686.      * Default value is null
  687.      *
  688.      * @access public
  689.      * @var float
  690.      */
  691.     var $image_max_ratio;
  692.  
  693.     /**
  694.      * Set this variable to set a minimum image width, below which the upload will be invalid
  695.      *
  696.      * Default value is null
  697.      *
  698.      * @access public
  699.      * @var integer
  700.      */
  701.     var $image_min_width;
  702.  
  703.     /**
  704.      * Set this variable to set a minimum image height, below which the upload will be invalid
  705.      *
  706.      * Default value is null
  707.      *
  708.      * @access public
  709.      * @var integer
  710.      */
  711.     var $image_min_height;
  712.  
  713.     /**
  714.      * Set this variable to set a minimum number of pixels for an image, below which the upload will be invalid
  715.      *
  716.      * Default value is null
  717.      *
  718.      * @access public
  719.      * @var long
  720.      */
  721.     var $image_min_pixels;
  722.  
  723.     /**
  724.      * Set this variable to set a minimum image aspect ratio, below which the upload will be invalid
  725.      *
  726.      * Note that ratio = width / height
  727.      *
  728.      * Default value is null
  729.      *
  730.      * @access public
  731.      * @var float
  732.      */
  733.     var $image_min_ratio;
  734.  
  735.     /**
  736.      * Compression level for PNG images
  737.      *
  738.      * Between 1 (fast but large files) and 9 (slow but smaller files)
  739.      *
  740.      * Default value is null (Zlib default)
  741.      *
  742.      * @access public
  743.      * @var integer
  744.      */
  745.     var $png_compression;
  746.  
  747.     /**
  748.      * Quality of JPEG created/converted destination image
  749.      *
  750.      * Default value is 85
  751.      *
  752.      * @access public
  753.      * @var integer
  754.      */
  755.     var $jpeg_quality;
  756.  
  757.     /**
  758.      * Determines the quality of the JPG image to fit a desired file size
  759.      *
  760.      * The JPG quality will be set between 1 and 100%
  761.      * The calculations are approximations.
  762.      *
  763.      * Value in bytes (integer) or shorthand byte values (string) is allowed.
  764.      * The available options are K (for Kilobytes), M (for Megabytes) and G (for Gigabytes)
  765.      *
  766.      * Default value is null (no calculations)
  767.      *
  768.      * @access public
  769.      * @var integer
  770.      */
  771.     var $jpeg_size;
  772.  
  773.     /**
  774.      * Turns the interlace bit on
  775.      *
  776.      * This is actually used only for JPEG images, and defaults to false
  777.      *
  778.      * @access public
  779.      * @var boolean
  780.      */
  781.     var $image_interlace;
  782.  
  783.     /**
  784.      * Flag set to true when the image is transparent
  785.      *
  786.      * This is actually used only for transparent GIFs
  787.      *
  788.      * @access public
  789.      * @var boolean
  790.      */
  791.     var $image_is_transparent;
  792.  
  793.     /**
  794.      * Transparent color in a palette
  795.      *
  796.      * This is actually used only for transparent GIFs
  797.      *
  798.      * @access public
  799.      * @var boolean
  800.      */
  801.     var $image_transparent_color;
  802.  
  803.     /**
  804.      * Background color, used to paint transparent areas with
  805.      *
  806.      * If set, it will forcibly remove transparency by painting transparent areas with the color
  807.      * This setting will fill in all transparent areas in PNG and GIF, as opposed to {@link image_default_color}
  808.      * which will do so only in BMP, JPEG, and alpha transparent areas in transparent GIFs
  809.      * This setting overrides {@link image_default_color}
  810.      *
  811.      * Default value is null
  812.      *
  813.      * @access public
  814.      * @var string
  815.      */
  816.     var $image_background_color;
  817.  
  818.     /**
  819.      * Default color for non alpha-transparent images
  820.      *
  821.      * This setting is to be used to define a background color for semi transparent areas
  822.      * of an alpha transparent when the output format doesn't support alpha transparency
  823.      * This is useful when, from an alpha transparent PNG image, or an image with alpha transparent features
  824.      * if you want to output it as a transparent GIFs for instance, you can set a blending color for transparent areas
  825.      * If you output in JPEG or BMP, this color will be used to fill in the previously transparent areas
  826.      *
  827.      * The default color white
  828.      *
  829.      * @access public
  830.      * @var boolean
  831.      */
  832.     var $image_default_color;
  833.  
  834.     /**
  835.      * Flag set to true when the image is not true color
  836.      *
  837.      * @access public
  838.      * @var boolean
  839.      */
  840.     var $image_is_palette;
  841.  
  842.     /**
  843.      * Corrects the image brightness
  844.      *
  845.      * Value can range between -127 and 127
  846.      *
  847.      * Default value is null
  848.      *
  849.      * @access public
  850.      * @var integer
  851.      */
  852.     var $image_brightness;
  853.  
  854.     /**
  855.      * Corrects the image contrast
  856.      *
  857.      * Value can range between -127 and 127
  858.      *
  859.      * Default value is null
  860.      *
  861.      * @access public
  862.      * @var integer
  863.      */
  864.     var $image_contrast;
  865.  
  866.     /**
  867.      * Changes the image opacity
  868.      *
  869.      * Value can range between 0 and 100
  870.      *
  871.      * Default value is null
  872.      *
  873.      * @access public
  874.      * @var integer
  875.      */
  876.     var $image_opacity;
  877.  
  878.     /**
  879.      * Applies threshold filter
  880.      *
  881.      * Value can range between -127 and 127
  882.      *
  883.      * Default value is null
  884.      *
  885.      * @access public
  886.      * @var integer
  887.      */
  888.     var $image_threshold;
  889.  
  890.     /**
  891.      * Applies a tint on the image
  892.      *
  893.      * Value is an hexadecimal color, such as #FFFFFF
  894.      *
  895.      * Default value is null
  896.      *
  897.      * @access public
  898.      * @var string;
  899.      */
  900.     var $image_tint_color;
  901.  
  902.     /**
  903.      * Applies a colored overlay on the image
  904.      *
  905.      * Value is an hexadecimal color, such as #FFFFFF
  906.      *
  907.      * To use with {@link image_overlay_opacity}
  908.      *
  909.      * Default value is null
  910.      *
  911.      * @access public
  912.      * @var string;
  913.      */
  914.     var $image_overlay_color;
  915.  
  916.     /**
  917.      * Sets the opacity for the colored overlay
  918.      *
  919.      * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
  920.      *
  921.      * Unless used with {@link image_overlay_color}, this setting has no effect
  922.      *
  923.      * Default value is 50
  924.      *
  925.      * @access public
  926.      * @var integer
  927.      */
  928.     var $image_overlay_opacity;
  929.  
  930.     /**
  931.      * Inverts the color of an image
  932.      *
  933.      * Default value is FALSE
  934.      *
  935.      * @access public
  936.      * @var boolean;
  937.      */
  938.     var $image_negative;
  939.  
  940.     /**
  941.      * Turns the image into greyscale
  942.      *
  943.      * Default value is FALSE
  944.      *
  945.      * @access public
  946.      * @var boolean;
  947.      */
  948.     var $image_greyscale;
  949.  
  950.     /**
  951.      * Pixelate an image
  952.      *
  953.      * Value is integer, represents the block size
  954.      *
  955.      * Default value is null
  956.      *
  957.      * @access public
  958.      * @var integer;
  959.      */
  960.     var $image_pixelate;
  961.  
  962.     /**
  963.      * Applies an unsharp mask, with alpha transparency support
  964.      *
  965.      * Beware that this unsharp mask is quite resource-intensive
  966.      *
  967.      * Default value is FALSE
  968.      *
  969.      * @access public
  970.      * @var boolean;
  971.      */
  972.     var $image_unsharp;
  973.  
  974.     /**
  975.      * Sets the unsharp mask amount
  976.      *
  977.      * Value is an integer between 0 and 500, typically between 50 and 200
  978.      *
  979.      * Unless used with {@link image_unsharp}, this setting has no effect
  980.      *
  981.      * Default value is 80
  982.      *
  983.      * @access public
  984.      * @var integer
  985.      */
  986.     var $image_unsharp_amount;
  987.  
  988.     /**
  989.      * Sets the unsharp mask radius
  990.      *
  991.      * Value is an integer between 0 and 50, typically between 0.5 and 1
  992.      * It is not recommended to change it, the default works best
  993.      *
  994.      * Unless used with {@link image_unsharp}, this setting has no effect
  995.      *
  996.      * From PHP 5.1, imageconvolution is used, and this setting has no effect
  997.      *
  998.      * Default value is 0.5
  999.      *
  1000.      * @access public
  1001.      * @var integer
  1002.      */
  1003.     var $image_unsharp_radius;
  1004.  
  1005.     /**
  1006.      * Sets the unsharp mask threshold
  1007.      *
  1008.      * Value is an integer between 0 and 255, typically between 0 and 5
  1009.      *
  1010.      * Unless used with {@link image_unsharp}, this setting has no effect
  1011.      *
  1012.      * Default value is 1
  1013.      *
  1014.      * @access public
  1015.      * @var integer
  1016.      */
  1017.     var $image_unsharp_threshold;
  1018.  
  1019.     /**
  1020.      * Adds a text label on the image
  1021.      *
  1022.      * Value is a string, any text. Text will not word-wrap, although you can use breaklines in your text "\n"
  1023.      *
  1024.      * If set, this setting allow the use of all other settings starting with image_text_
  1025.      *
  1026.      * Replacement tokens can be used in the string:
  1027.      * <pre>
  1028.      * gd_version    src_name       src_name_body src_name_ext
  1029.      * src_pathname  src_mime       src_x         src_y
  1030.      * src_type      src_bits       src_pixels
  1031.      * src_size      src_size_kb    src_size_mb   src_size_human
  1032.      * dst_path      dst_name_body  dst_pathname
  1033.      * dst_name      dst_name_ext   dst_x         dst_y
  1034.      * date          time           host          server        ip
  1035.      * </pre>
  1036.      * The tokens must be enclosed in square brackets: [dst_x] will be replaced by the width of the picture
  1037.      *
  1038.      * Default value is null
  1039.      *
  1040.      * @access public
  1041.      * @var string;
  1042.      */
  1043.     var $image_text;
  1044.  
  1045.     /**
  1046.      * Sets the text direction for the text label
  1047.      *
  1048.      * Value is either 'h' or 'v', as in horizontal and vertical
  1049.      *
  1050.      * Note that if you use a TrueType font, you can use {@link image_text_angle} instead
  1051.      *
  1052.      * Default value is h (horizontal)
  1053.      *
  1054.      * @access public
  1055.      * @var string;
  1056.      */
  1057.     var $image_text_direction;
  1058.  
  1059.     /**
  1060.      * Sets the text color for the text label
  1061.      *
  1062.      * Value is an hexadecimal color, such as #FFFFFF
  1063.      *
  1064.      * Default value is #FFFFFF (white)
  1065.      *
  1066.      * @access public
  1067.      * @var string;
  1068.      */
  1069.     var $image_text_color;
  1070.  
  1071.     /**
  1072.      * Sets the text opacity in the text label
  1073.      *
  1074.      * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
  1075.      *
  1076.      * Default value is 100
  1077.      *
  1078.      * @access public
  1079.      * @var integer
  1080.      */
  1081.     var $image_text_opacity;
  1082.  
  1083.     /**
  1084.      * Sets the text background color for the text label
  1085.      *
  1086.      * Value is an hexadecimal color, such as #FFFFFF
  1087.      *
  1088.      * Default value is null (no background)
  1089.      *
  1090.      * @access public
  1091.      * @var string;
  1092.      */
  1093.     var $image_text_background;
  1094.  
  1095.     /**
  1096.      * Sets the text background opacity in the text label
  1097.      *
  1098.      * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
  1099.      *
  1100.      * Default value is 100
  1101.      *
  1102.      * @access public
  1103.      * @var integer
  1104.      */
  1105.     var $image_text_background_opacity;
  1106.  
  1107.     /**
  1108.      * Sets the text font in the text label
  1109.      *
  1110.      * Value is a an integer between 1 and 5 for GD built-in fonts. 1 is the smallest font, 5 the biggest
  1111.      * Value can also be a string, which represents the path to a GDF or TTF font (TrueType).
  1112.      *
  1113.      * Default value is 5
  1114.      *
  1115.      * @access public
  1116.      * @var mixed;
  1117.      */
  1118.     var $image_text_font;
  1119.  
  1120.     /**
  1121.      * Sets the text font size for TrueType fonts
  1122.      *
  1123.      * Value is a an integer, and represents the font size in pixels (GD1) or points (GD1)
  1124.      *
  1125.      * Note that this setting is only applicable to TrueType fonts, and has no effects with GD fonts
  1126.      *
  1127.      * Default value is 16
  1128.      *
  1129.      * @access public
  1130.      * @var integer;
  1131.      */
  1132.     var $image_text_size;
  1133.  
  1134.     /**
  1135.      * Sets the text angle for TrueType fonts
  1136.      *
  1137.      * Value is a an integer between 0 and 360, in degrees, with 0 degrees being left-to-right reading text.
  1138.      *
  1139.      * Note that this setting is only applicable to TrueType fonts, and has no effects with GD fonts
  1140.      * For GD fonts, you can use {@link image_text_direction} instead
  1141.      *
  1142.      * Default value is null (so it is determined by the value of {@link image_text_direction})
  1143.      *
  1144.      * @access public
  1145.      * @var integer;
  1146.      */
  1147.     var $image_text_angle;
  1148.  
  1149.     /**
  1150.      * Sets the text label position within the image
  1151.      *
  1152.      * Value is one or two out of 'TBLR' (top, bottom, left, right)
  1153.      *
  1154.      * The positions are as following:
  1155.      * <pre>
  1156.      *                        TL  T  TR
  1157.      *                        L       R
  1158.      *                        BL  B  BR
  1159.      * </pre>
  1160.      *
  1161.      * Default value is null (centered, horizontal and vertical)
  1162.      *
  1163.      * Note that is {@link image_text_x} and {@link image_text_y} are used, this setting has no effect
  1164.      *
  1165.      * @access public
  1166.      * @var string;
  1167.      */
  1168.     var $image_text_position;
  1169.  
  1170.     /**
  1171.      * Sets the text label absolute X position within the image
  1172.      *
  1173.      * Value is in pixels, representing the distance between the left of the image and the label
  1174.      * If a negative value is used, it will represent the distance between the right of the image and the label
  1175.      *
  1176.      * Default value is null (so {@link image_text_position} is used)
  1177.      *
  1178.      * @access public
  1179.      * @var integer
  1180.      */
  1181.     var $image_text_x;
  1182.  
  1183.     /**
  1184.      * Sets the text label absolute Y position within the image
  1185.      *
  1186.      * Value is in pixels, representing the distance between the top of the image and the label
  1187.      * If a negative value is used, it will represent the distance between the bottom of the image and the label
  1188.      *
  1189.      * Default value is null (so {@link image_text_position} is used)
  1190.      *
  1191.      * @access public
  1192.      * @var integer
  1193.      */
  1194.     var $image_text_y;
  1195.  
  1196.     /**
  1197.      * Sets the text label padding
  1198.      *
  1199.      * Value is in pixels, representing the distance between the text and the label background border
  1200.      *
  1201.      * Default value is 0
  1202.      *
  1203.      * This setting can be overriden by {@link image_text_padding_x} and {@link image_text_padding_y}
  1204.      *
  1205.      * @access public
  1206.      * @var integer
  1207.      */
  1208.     var $image_text_padding;
  1209.  
  1210.     /**
  1211.      * Sets the text label horizontal padding
  1212.      *
  1213.      * Value is in pixels, representing the distance between the text and the left and right label background borders
  1214.      *
  1215.      * Default value is null
  1216.      *
  1217.      * If set, this setting overrides the horizontal part of {@link image_text_padding}
  1218.      *
  1219.      * @access public
  1220.      * @var integer
  1221.      */
  1222.     var $image_text_padding_x;
  1223.  
  1224.     /**
  1225.      * Sets the text label vertical padding
  1226.      *
  1227.      * Value is in pixels, representing the distance between the text and the top and bottom label background borders
  1228.      *
  1229.      * Default value is null
  1230.      *
  1231.      * If set, his setting overrides the vertical part of {@link image_text_padding}
  1232.      *
  1233.      * @access public
  1234.      * @var integer
  1235.      */
  1236.     var $image_text_padding_y;
  1237.  
  1238.     /**
  1239.      * Sets the text alignment
  1240.      *
  1241.      * Value is a string, which can be either 'L', 'C' or 'R'
  1242.      *
  1243.      * Default value is 'C'
  1244.      *
  1245.      * This setting is relevant only if the text has several lines.
  1246.      *
  1247.      * Note that this setting is only applicable to GD fonts, and has no effects with TrueType fonts
  1248.      *
  1249.      * @access public
  1250.      * @var string;
  1251.      */
  1252.     var $image_text_alignment;
  1253.  
  1254.     /**
  1255.      * Sets the text line spacing
  1256.      *
  1257.      * Value is an integer, in pixels
  1258.      *
  1259.      * Default value is 0
  1260.      *
  1261.      * This setting is relevant only if the text has several lines.
  1262.      *
  1263.      * Note that this setting is only applicable to GD fonts, and has no effects with TrueType fonts
  1264.      *
  1265.      * @access public
  1266.      * @var integer
  1267.      */
  1268.     var $image_text_line_spacing;
  1269.  
  1270.     /**
  1271.      * Sets the height of the reflection
  1272.      *
  1273.      * Value is an integer in pixels, or a string which format can be in pixels or percentage.
  1274.      * For instance, values can be : 40, '40', '40px' or '40%'
  1275.      *
  1276.      * Default value is null, no reflection
  1277.      *
  1278.      * @access public
  1279.      * @var mixed;
  1280.      */
  1281.     var $image_reflection_height;
  1282.  
  1283.     /**
  1284.      * Sets the space between the source image and its relection
  1285.      *
  1286.      * Value is an integer in pixels, which can be negative
  1287.      *
  1288.      * Default value is 2
  1289.      *
  1290.      * This setting is relevant only if {@link image_reflection_height} is set
  1291.      *
  1292.      * @access public
  1293.      * @var integer
  1294.      */
  1295.     var $image_reflection_space;
  1296.  
  1297.     /**
  1298.      * Sets the initial opacity of the reflection
  1299.      *
  1300.      * Value is an integer between 0 (no opacity) and 100 (full opacity).
  1301.      * The reflection will start from {@link image_reflection_opacity} and end up at 0
  1302.      *
  1303.      * Default value is 60
  1304.      *
  1305.      * This setting is relevant only if {@link image_reflection_height} is set
  1306.      *
  1307.      * @access public
  1308.      * @var integer
  1309.      */
  1310.     var $image_reflection_opacity;
  1311.  
  1312.     /**
  1313.      * Automatically rotates the image according to EXIF data (JPEG only)
  1314.      *
  1315.      * Default value is true
  1316.      *
  1317.      * @access public
  1318.      * @var boolean;
  1319.      */
  1320.     var $image_auto_rotate;
  1321.  
  1322.     /**
  1323.      * Flips the image vertically or horizontally
  1324.      *
  1325.      * Value is either 'h' or 'v', as in horizontal and vertical
  1326.      *
  1327.      * Default value is null (no flip)
  1328.      *
  1329.      * @access public
  1330.      * @var string;
  1331.      */
  1332.     var $image_flip;
  1333.  
  1334.     /**
  1335.      * Rotates the image by increments of 45 degrees
  1336.      *
  1337.      * Value is either 90, 180 or 270
  1338.      *
  1339.      * Default value is null (no rotation)
  1340.      *
  1341.      * @access public
  1342.      * @var string;
  1343.      */
  1344.     var $image_rotate;
  1345.  
  1346.     /**
  1347.      * Crops an image
  1348.      *
  1349.      * Values are four dimensions, or two, or one (CSS style)
  1350.      * They represent the amount cropped top, right, bottom and left.
  1351.      * These values can either be in an array, or a space separated string.
  1352.      * Each value can be in pixels (with or without 'px'), or percentage (of the source image)
  1353.      *
  1354.      * For instance, are valid:
  1355.      * <pre>
  1356.      * $foo->image_crop = 20                  OR array(20);
  1357.      * $foo->image_crop = '20px'              OR array('20px');
  1358.      * $foo->image_crop = '20 40'             OR array('20', 40);
  1359.      * $foo->image_crop = '-20 25%'           OR array(-20, '25%');
  1360.      * $foo->image_crop = '20px 25%'          OR array('20px', '25%');
  1361.      * $foo->image_crop = '20% 25%'           OR array('20%', '25%');
  1362.      * $foo->image_crop = '20% 25% 10% 30%'   OR array('20%', '25%', '10%', '30%');
  1363.      * $foo->image_crop = '20px 25px 2px 2px' OR array('20px', '25%px', '2px', '2px');
  1364.      * $foo->image_crop = '20 25% 40px 10%'   OR array(20, '25%', '40px', '10%');
  1365.      * </pre>
  1366.      *
  1367.      * If a value is negative, the image will be expanded, and the extra parts will be filled with black
  1368.      *
  1369.      * Default value is null (no cropping)
  1370.      *
  1371.      * @access public
  1372.      * @var string OR array;
  1373.      */
  1374.     var $image_crop;
  1375.  
  1376.     /**
  1377.      * Crops an image, before an eventual resizing
  1378.      *
  1379.      * See {@link image_crop} for valid formats
  1380.      *
  1381.      * Default value is null (no cropping)
  1382.      *
  1383.      * @access public
  1384.      * @var string OR array;
  1385.      */
  1386.     var $image_precrop;
  1387.  
  1388.     /**
  1389.      * Adds a bevel border on the image
  1390.      *
  1391.      * Value is a positive integer, representing the thickness of the bevel
  1392.      *
  1393.      * If the bevel colors are the same as the background, it makes a fade out effect
  1394.      *
  1395.      * Default value is null (no bevel)
  1396.      *
  1397.      * @access public
  1398.      * @var integer
  1399.      */
  1400.     var $image_bevel;
  1401.  
  1402.     /**
  1403.      * Top and left bevel color
  1404.      *
  1405.      * Value is a color, in hexadecimal format
  1406.      * This setting is used only if {@link image_bevel} is set
  1407.      *
  1408.      * Default value is #FFFFFF
  1409.      *
  1410.      * @access public
  1411.      * @var string;
  1412.      */
  1413.     var $image_bevel_color1;
  1414.  
  1415.     /**
  1416.      * Right and bottom bevel color
  1417.      *
  1418.      * Value is a color, in hexadecimal format
  1419.      * This setting is used only if {@link image_bevel} is set
  1420.      *
  1421.      * Default value is #000000
  1422.      *
  1423.      * @access public
  1424.      * @var string;
  1425.      */
  1426.     var $image_bevel_color2;
  1427.  
  1428.     /**
  1429.      * Adds a single-color border on the outer of the image
  1430.      *
  1431.      * Values are four dimensions, or two, or one (CSS style)
  1432.      * They represent the border thickness top, right, bottom and left.
  1433.      * These values can either be in an array, or a space separated string.
  1434.      * Each value can be in pixels (with or without 'px'), or percentage (of the source image)
  1435.      *
  1436.      * See {@link image_crop} for valid formats
  1437.      *
  1438.      * If a value is negative, the image will be cropped.
  1439.      * Note that the dimensions of the picture will be increased by the borders' thickness
  1440.      *
  1441.      * Default value is null (no border)
  1442.      *
  1443.      * @access public
  1444.      * @var integer
  1445.      */
  1446.     var $image_border;
  1447.  
  1448.     /**
  1449.      * Border color
  1450.      *
  1451.      * Value is a color, in hexadecimal format.
  1452.      * This setting is used only if {@link image_border} is set
  1453.      *
  1454.      * Default value is #FFFFFF
  1455.      *
  1456.      * @access public
  1457.      * @var string;
  1458.      */
  1459.     var $image_border_color;
  1460.  
  1461.     /**
  1462.      * Sets the opacity for the borders
  1463.      *
  1464.      * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
  1465.      *
  1466.      * Unless used with {@link image_border}, this setting has no effect
  1467.      *
  1468.      * Default value is 100
  1469.      *
  1470.      * @access public
  1471.      * @var integer
  1472.      */
  1473.     var $image_border_opacity;
  1474.  
  1475.     /**
  1476.      * Adds a fading-to-transparent border on the image
  1477.      *
  1478.      * Values are four dimensions, or two, or one (CSS style)
  1479.      * They represent the border thickness top, right, bottom and left.
  1480.      * These values can either be in an array, or a space separated string.
  1481.      * Each value can be in pixels (with or without 'px'), or percentage (of the source image)
  1482.      *
  1483.      * See {@link image_crop} for valid formats
  1484.      *
  1485.      * Note that the dimensions of the picture will not be increased by the borders' thickness
  1486.      *
  1487.      * Default value is null (no border)
  1488.      *
  1489.      * @access public
  1490.      * @var integer
  1491.      */
  1492.     var $image_border_transparent;
  1493.  
  1494.     /**
  1495.      * Adds a multi-color frame on the outer of the image
  1496.      *
  1497.      * Value is an integer. Two values are possible for now:
  1498.      * 1 for flat border, meaning that the frame is mirrored horizontally and vertically
  1499.      * 2 for crossed border, meaning that the frame will be inversed, as in a bevel effect
  1500.      *
  1501.      * The frame will be composed of colored lines set in {@link image_frame_colors}
  1502.      *
  1503.      * Note that the dimensions of the picture will be increased by the borders' thickness
  1504.      *
  1505.      * Default value is null (no frame)
  1506.      *
  1507.      * @access public
  1508.      * @var integer
  1509.      */
  1510.     var $image_frame;
  1511.  
  1512.     /**
  1513.      * Sets the colors used to draw a frame
  1514.      *
  1515.      * Values is a list of n colors in hexadecimal format.
  1516.      * These values can either be in an array, or a space separated string.
  1517.      *
  1518.      * The colors are listed in the following order: from the outset of the image to its center
  1519.      *
  1520.      * For instance, are valid:
  1521.      * <pre>
  1522.      * $foo->image_frame_colors = '#FFFFFF #999999 #666666 #000000';
  1523.      * $foo->image_frame_colors = array('#FFFFFF', '#999999', '#666666', '#000000');
  1524.      * </pre>
  1525.      *
  1526.      * This setting is used only if {@link image_frame} is set
  1527.      *
  1528.      * Default value is '#FFFFFF #999999 #666666 #000000'
  1529.      *
  1530.      * @access public
  1531.      * @var string OR array;
  1532.      */
  1533.     var $image_frame_colors;
  1534.  
  1535.     /**
  1536.      * Sets the opacity for the frame
  1537.      *
  1538.      * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque)
  1539.      *
  1540.      * Unless used with {@link image_frame}, this setting has no effect
  1541.      *
  1542.      * Default value is 100
  1543.      *
  1544.      * @access public
  1545.      * @var integer
  1546.      */
  1547.     var $image_frame_opacity;
  1548.  
  1549.     /**
  1550.      * Adds a watermark on the image
  1551.      *
  1552.      * Value is a local image filename, relative or absolute. GIF, JPG, BMP and PNG are supported, as well as PNG alpha.
  1553.      *
  1554.      * If set, this setting allow the use of all other settings starting with image_watermark_
  1555.      *
  1556.      * Default value is null
  1557.      *
  1558.      * @access public
  1559.      * @var string;
  1560.      */
  1561.     var $image_watermark;
  1562.  
  1563.     /**
  1564.      * Sets the watermarkposition within the image
  1565.      *
  1566.      * Value is one or two out of 'TBLR' (top, bottom, left, right)
  1567.      *
  1568.      * The positions are as following:   TL  T  TR
  1569.      *                                   L       R
  1570.      *                                   BL  B  BR
  1571.      *
  1572.      * Default value is null (centered, horizontal and vertical)
  1573.      *
  1574.      * Note that is {@link image_watermark_x} and {@link image_watermark_y} are used, this setting has no effect
  1575.      *
  1576.      * @access public
  1577.      * @var string;
  1578.      */
  1579.     var $image_watermark_position;
  1580.  
  1581.     /**
  1582.      * Sets the watermark absolute X position within the image
  1583.      *
  1584.      * Value is in pixels, representing the distance between the top of the image and the watermark
  1585.      * If a negative value is used, it will represent the distance between the bottom of the image and the watermark
  1586.      *
  1587.      * Default value is null (so {@link image_watermark_position} is used)
  1588.      *
  1589.      * @access public
  1590.      * @var integer
  1591.      */
  1592.     var $image_watermark_x;
  1593.  
  1594.     /**
  1595.      * Sets the twatermark absolute Y position within the image
  1596.      *
  1597.      * Value is in pixels, representing the distance between the left of the image and the watermark
  1598.      * If a negative value is used, it will represent the distance between the right of the image and the watermark
  1599.      *
  1600.      * Default value is null (so {@link image_watermark_position} is used)
  1601.      *
  1602.      * @access public
  1603.      * @var integer
  1604.      */
  1605.     var $image_watermark_y;
  1606.  
  1607.     /**
  1608.      * Prevents the watermark to be resized up if it is smaller than the image
  1609.      *
  1610.      * If the watermark if smaller than the destination image, taking in account the desired watermark position
  1611.      * then it will be resized up to fill in the image (minus the {@link image_watermark_x} or {@link image_watermark_y} values)
  1612.      *
  1613.      * If you don't want your watermark to be resized in any way, then
  1614.      * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to true
  1615.      * If you want your watermark to be resized up or doan to fill in the image better, then
  1616.      * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to false
  1617.      *
  1618.      * Default value is true (so the watermark will not be resized up, which is the behaviour most people expect)
  1619.      *
  1620.      * @access public
  1621.      * @var integer
  1622.      */
  1623.     var $image_watermark_no_zoom_in;
  1624.  
  1625.     /**
  1626.      * Prevents the watermark to be resized down if it is bigger than the image
  1627.      *
  1628.      * If the watermark if bigger than the destination image, taking in account the desired watermark position
  1629.      * then it will be resized down to fit in the image (minus the {@link image_watermark_x} or {@link image_watermark_y} values)
  1630.      *
  1631.      * If you don't want your watermark to be resized in any way, then
  1632.      * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to true
  1633.      * If you want your watermark to be resized up or doan to fill in the image better, then
  1634.      * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to false
  1635.      *
  1636.      * Default value is false (so the watermark may be shrinked to fit in the image)
  1637.      *
  1638.      * @access public
  1639.      * @var integer
  1640.      */
  1641.     var $image_watermark_no_zoom_out;
  1642.  
  1643.     /**
  1644.      * List of MIME types per extension
  1645.      *
  1646.      * @access private
  1647.      * @var array
  1648.      */
  1649.     var $mime_types;
  1650.  
  1651.     /**
  1652.      * Allowed MIME types
  1653.      *
  1654.      * Default is a selection of safe mime-types, but you might want to change it
  1655.      *
  1656.      * Simple wildcards are allowed, such as image/* or application/*
  1657.      * If there is only one MIME type allowed, then it can be a string instead of an array
  1658.      *
  1659.      * @access public
  1660.      * @var array OR string
  1661.      */
  1662.     var $allowed;
  1663.  
  1664.     /**
  1665.      * Forbidden MIME types
  1666.      *
  1667.      * Default is a selection of safe mime-types, but you might want to change it
  1668.      * To only check for forbidden MIME types, and allow everything else, set {@link allowed} to array('* / *') without the spaces
  1669.      *
  1670.      * Simple wildcards are allowed, such as image/* or application/*
  1671.      * If there is only one MIME type forbidden, then it can be a string instead of an array
  1672.      *
  1673.      * @access public
  1674.      * @var array OR string
  1675.      */
  1676.     var $forbidden;
  1677.  
  1678.     /**
  1679.      * Array of translated error messages
  1680.      *
  1681.      * By default, the language is english (en_GB)
  1682.      * Translations can be in separate files, in a lang/ subdirectory
  1683.      *
  1684.      * @access public
  1685.      * @var array
  1686.      */
  1687.     var $translation;
  1688.  
  1689.     /**
  1690.      * Language selected for the translations
  1691.      *
  1692.      * By default, the language is english ("en_GB")
  1693.      *
  1694.      * @access public
  1695.      * @var array
  1696.      */
  1697.     var $lang;
  1698.  
  1699.     /**
  1700.      * Init or re-init all the processing variables to their default values
  1701.      *
  1702.      * This function is called in the constructor, and after each call of {@link process}
  1703.      *
  1704.      * @access private
  1705.      */
  1706.     function init() {
  1707.  
  1708.         // overiddable variables
  1709.         $this->file_new_name_body       = null;     // replace the name body
  1710.         $this->file_name_body_add       = null;     // append to the name body
  1711.         $this->file_name_body_pre       = null;     // prepend to the name body
  1712.         $this->file_new_name_ext        = null;     // replace the file extension
  1713.         $this->file_safe_name           = true;     // format safely the filename
  1714.         $this->file_force_extension     = true;     // forces extension if there isn't one
  1715.         $this->file_overwrite           = false;    // allows overwritting if the file already exists
  1716.         $this->file_auto_rename         = true;     // auto-rename if the file already exists
  1717.         $this->dir_auto_create          = true;     // auto-creates directory if missing
  1718.         $this->dir_auto_chmod           = true;     // auto-chmod directory if not writeable
  1719.         $this->dir_chmod                = 0777;     // default chmod to use
  1720.  
  1721.         $this->no_script                = true;     // turns scripts into test files
  1722.         $this->mime_check               = true;     // checks the mime type against the allowed list
  1723.  
  1724.         // these are the different MIME detection methods. if one of these method doesn't work on your
  1725.         // system, you can deactivate it here; just set it to false
  1726.         $this->mime_fileinfo            = true;     // MIME detection with Fileinfo PECL extension
  1727.         $this->mime_file                = true;     // MIME detection with UNIX file() command
  1728.         $this->mime_magic               = true;     // MIME detection with mime_magic (mime_content_type())
  1729.         $this->mime_getimagesize        = true;     // MIME detection with getimagesize()
  1730.  
  1731.         // get the default max size from php.ini
  1732.         $this->file_max_size_raw = trim(ini_get('upload_max_filesize'));
  1733.         $this->file_max_size = $this->getsize($this->file_max_size_raw);
  1734.  
  1735.         $this->image_resize             = false;    // resize the image
  1736.         $this->image_convert            = '';       // convert. values :''; 'png'; 'jpeg'; 'gif'; 'bmp'
  1737.  
  1738.         $this->image_x                  = 150;
  1739.         $this->image_y                  = 150;
  1740.         $this->image_ratio              = false;    // keeps aspect ratio with x and y dimensions
  1741.         $this->image_ratio_crop         = false;    // keeps aspect ratio with x and y dimensions, filling the space
  1742.         $this->image_ratio_fill         = false;    // keeps aspect ratio with x and y dimensions, fitting the image in the space, and coloring the rest
  1743.         $this->image_ratio_pixels       = false;    // keeps aspect ratio, calculating x and y so that the image is approx the set number of pixels
  1744.         $this->image_ratio_x            = false;    // calculate the $image_x if true
  1745.         $this->image_ratio_y            = false;    // calculate the $image_y if true
  1746.         $this->image_ratio_no_zoom_in   = false;
  1747.         $this->image_ratio_no_zoom_out  = false;
  1748.         $this->image_no_enlarging       = false;
  1749.         $this->image_no_shrinking       = false;
  1750.  
  1751.         $this->png_compression          = null;
  1752.         $this->jpeg_quality             = 85;
  1753.         $this->jpeg_size                = null;
  1754.         $this->image_interlace          = false;
  1755.         $this->image_is_transparent     = false;
  1756.         $this->image_transparent_color  = null;
  1757.         $this->image_background_color   = null;
  1758.         $this->image_default_color      = '#ffffff';
  1759.         $this->image_is_palette         = false;
  1760.  
  1761.         $this->image_max_width          = null;
  1762.         $this->image_max_height         = null;
  1763.         $this->image_max_pixels         = null;
  1764.         $this->image_max_ratio          = null;
  1765.         $this->image_min_width          = null;
  1766.         $this->image_min_height         = null;
  1767.         $this->image_min_pixels         = null;
  1768.         $this->image_min_ratio          = null;
  1769.  
  1770.         $this->image_brightness         = null;
  1771.         $this->image_contrast           = null;
  1772.         $this->image_opacity            = null;
  1773.         $this->image_threshold          = null;
  1774.         $this->image_tint_color         = null;
  1775.         $this->image_overlay_color      = null;
  1776.         $this->image_overlay_opacity    = null;
  1777.         $this->image_negative           = false;
  1778.         $this->image_greyscale          = false;
  1779.         $this->image_pixelate           = null;
  1780.         $this->image_unsharp            = false;
  1781.         $this->image_unsharp_amount     = 80;
  1782.         $this->image_unsharp_radius     = 0.5;
  1783.         $this->image_unsharp_threshold  = 1;
  1784.  
  1785.         $this->image_text               = null;
  1786.         $this->image_text_direction     = null;
  1787.         $this->image_text_color         = '#FFFFFF';
  1788.         $this->image_text_opacity       = 100;
  1789.         $this->image_text_background    = null;
  1790.         $this->image_text_background_opacity = 100;
  1791.         $this->image_text_font          = 5;
  1792.         $this->image_text_size          = 16;
  1793.         $this->image_text_angle         = null;
  1794.         $this->image_text_x             = null;
  1795.         $this->image_text_y             = null;
  1796.         $this->image_text_position      = null;
  1797.         $this->image_text_padding       = 0;
  1798.         $this->image_text_padding_x     = null;
  1799.         $this->image_text_padding_y     = null;
  1800.         $this->image_text_alignment     = 'C';
  1801.         $this->image_text_line_spacing  = 0;
  1802.  
  1803.         $this->image_reflection_height  = null;
  1804.         $this->image_reflection_space   = 2;
  1805.         $this->image_reflection_opacity = 60;
  1806.  
  1807.         $this->image_watermark          = null;
  1808.         $this->image_watermark_x        = null;
  1809.         $this->image_watermark_y        = null;
  1810.         $this->image_watermark_position = null;
  1811.         $this->image_watermark_no_zoom_in  = true;
  1812.         $this->image_watermark_no_zoom_out = false;
  1813.  
  1814.         $this->image_flip               = null;
  1815.         $this->image_auto_rotate        = true;
  1816.         $this->image_rotate             = null;
  1817.         $this->image_crop               = null;
  1818.         $this->image_precrop            = null;
  1819.  
  1820.         $this->image_bevel              = null;
  1821.         $this->image_bevel_color1       = '#FFFFFF';
  1822.         $this->image_bevel_color2       = '#000000';
  1823.         $this->image_border             = null;
  1824.         $this->image_border_color       = '#FFFFFF';
  1825.         $this->image_border_opacity     = 100;
  1826.         $this->image_border_transparent = null;
  1827.         $this->image_frame              = null;
  1828.         $this->image_frame_colors       = '#FFFFFF #999999 #666666 #000000';
  1829.         $this->image_frame_opacity      = 100;
  1830.  
  1831.         $this->forbidden = array();
  1832.         $this->allowed = array(
  1833.             'application/arj',
  1834.             'application/excel',
  1835.             'application/gnutar',
  1836.             'application/mspowerpoint',
  1837.             'application/msword',
  1838.             'application/octet-stream',
  1839.             'application/onenote',
  1840.             'application/pdf',
  1841.             'application/plain',
  1842.             'application/postscript',
  1843.             'application/powerpoint',
  1844.             'application/rar',
  1845.             'application/rtf',
  1846.             'application/vnd.ms-excel',
  1847.             'application/vnd.ms-excel.addin.macroEnabled.12',
  1848.             'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
  1849.             'application/vnd.ms-excel.sheet.macroEnabled.12',
  1850.             'application/vnd.ms-excel.template.macroEnabled.12',
  1851.             'application/vnd.ms-office',
  1852.             'application/vnd.ms-officetheme',
  1853.             'application/vnd.ms-powerpoint',
  1854.             'application/vnd.ms-powerpoint.addin.macroEnabled.12',
  1855.             'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
  1856.             'application/vnd.ms-powerpoint.slide.macroEnabled.12',
  1857.             'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
  1858.             'application/vnd.ms-powerpoint.template.macroEnabled.12',
  1859.             'application/vnd.ms-word',
  1860.             'application/vnd.ms-word.document.macroEnabled.12',
  1861.             'application/vnd.ms-word.template.macroEnabled.12',
  1862.             'application/vnd.oasis.opendocument.chart',
  1863.             'application/vnd.oasis.opendocument.database',
  1864.             'application/vnd.oasis.opendocument.formula',
  1865.             'application/vnd.oasis.opendocument.graphics',
  1866.             'application/vnd.oasis.opendocument.graphics-template',
  1867.             'application/vnd.oasis.opendocument.image',
  1868.             'application/vnd.oasis.opendocument.presentation',
  1869.             'application/vnd.oasis.opendocument.presentation-template',
  1870.             'application/vnd.oasis.opendocument.spreadsheet',
  1871.             'application/vnd.oasis.opendocument.spreadsheet-template',
  1872.             'application/vnd.oasis.opendocument.text',
  1873.             'application/vnd.oasis.opendocument.text-master',
  1874.             'application/vnd.oasis.opendocument.text-template',
  1875.             'application/vnd.oasis.opendocument.text-web',
  1876.             'application/vnd.openofficeorg.extension',
  1877.             'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  1878.             'application/vnd.openxmlformats-officedocument.presentationml.slide',
  1879.             'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
  1880.             'application/vnd.openxmlformats-officedocument.presentationml.template',
  1881.             'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  1882.             'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
  1883.             'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  1884.             'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  1885.             'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
  1886.             'application/vocaltec-media-file',
  1887.             'application/wordperfect',
  1888.             'application/x-bittorrent',
  1889.             'application/x-bzip',
  1890.             'application/x-bzip2',
  1891.             'application/x-compressed',
  1892.             'application/x-excel',
  1893.             'application/x-gzip',
  1894.             'application/x-latex',
  1895.             'application/x-midi',
  1896.             'application/xml',
  1897.             'application/x-msexcel',
  1898.             'application/x-rar',
  1899.             'application/x-rar-compressed',
  1900.             'application/x-rtf',
  1901.             'application/x-shockwave-flash',
  1902.             'application/x-sit',
  1903.             'application/x-stuffit',
  1904.             'application/x-troff-msvideo',
  1905.             'application/x-zip',
  1906.             'application/x-zip-compressed',
  1907.             'application/zip',
  1908.             'audio/*',
  1909.             'image/*',
  1910.             'multipart/x-gzip',
  1911.             'multipart/x-zip',
  1912.             'text/plain',
  1913.             'text/rtf',
  1914.             'text/richtext',
  1915.             'text/xml',
  1916.             'video/*',
  1917.             'text/csv'
  1918.         );
  1919.  
  1920.         $this->mime_types = array(
  1921.             'jpg' => 'image/jpeg',
  1922.             'jpeg' => 'image/jpeg',
  1923.             'jpe' => 'image/jpeg',
  1924.             'gif' => 'image/gif',
  1925.             'png' => 'image/png',
  1926.             'bmp' => 'image/bmp',
  1927.             'flif' => 'image/flif',
  1928.             'flv' => 'video/x-flv',
  1929.             'js' => 'application/x-javascript',
  1930.             'json' => 'application/json',
  1931.             'tiff' => 'image/tiff',
  1932.             'css' => 'text/css',
  1933.             'xml' => 'application/xml',
  1934.             'doc' => 'application/msword',
  1935.             'xls' => 'application/vnd.ms-excel',
  1936.             'xlt' => 'application/vnd.ms-excel',
  1937.             'xlm' => 'application/vnd.ms-excel',
  1938.             'xld' => 'application/vnd.ms-excel',
  1939.             'xla' => 'application/vnd.ms-excel',
  1940.             'xlc' => 'application/vnd.ms-excel',
  1941.             'xlw' => 'application/vnd.ms-excel',
  1942.             'xll' => 'application/vnd.ms-excel',
  1943.             'ppt' => 'application/vnd.ms-powerpoint',
  1944.             'pps' => 'application/vnd.ms-powerpoint',
  1945.             'rtf' => 'application/rtf',
  1946.             'pdf' => 'application/pdf',
  1947.             'html' => 'text/html',
  1948.             'htm' => 'text/html',
  1949.             'php' => 'text/html',
  1950.             'txt' => 'text/plain',
  1951.             'mpeg' => 'video/mpeg',
  1952.             'mpg' => 'video/mpeg',
  1953.             'mpe' => 'video/mpeg',
  1954.             'mp3' => 'audio/mpeg3',
  1955.             'wav' => 'audio/wav',
  1956.             'aiff' => 'audio/aiff',
  1957.             'aif' => 'audio/aiff',
  1958.             'avi' => 'video/msvideo',
  1959.             'wmv' => 'video/x-ms-wmv',
  1960.             'mov' => 'video/quicktime',
  1961.             'zip' => 'application/zip',
  1962.             'tar' => 'application/x-tar',
  1963.             'swf' => 'application/x-shockwave-flash',
  1964.             'odt' => 'application/vnd.oasis.opendocument.text',
  1965.             'ott' => 'application/vnd.oasis.opendocument.text-template',
  1966.             'oth' => 'application/vnd.oasis.opendocument.text-web',
  1967.             'odm' => 'application/vnd.oasis.opendocument.text-master',
  1968.             'odg' => 'application/vnd.oasis.opendocument.graphics',
  1969.             'otg' => 'application/vnd.oasis.opendocument.graphics-template',
  1970.             'odp' => 'application/vnd.oasis.opendocument.presentation',
  1971.             'otp' => 'application/vnd.oasis.opendocument.presentation-template',
  1972.             'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
  1973.             'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
  1974.             'odc' => 'application/vnd.oasis.opendocument.chart',
  1975.             'odf' => 'application/vnd.oasis.opendocument.formula',
  1976.             'odb' => 'application/vnd.oasis.opendocument.database',
  1977.             'odi' => 'application/vnd.oasis.opendocument.image',
  1978.             'oxt' => 'application/vnd.openofficeorg.extension',
  1979.             'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  1980.             'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
  1981.             'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
  1982.             'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
  1983.             'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  1984.             'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
  1985.             'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
  1986.             'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
  1987.             'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
  1988.             'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
  1989.             'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  1990.             'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
  1991.             'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
  1992.             'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
  1993.             'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
  1994.             'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
  1995.             'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
  1996.             'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
  1997.             'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
  1998.             'thmx' => 'application/vnd.ms-officetheme',
  1999.             'onetoc' => 'application/onenote',
  2000.             'onetoc2' => 'application/onenote',
  2001.             'onetmp' => 'application/onenote',
  2002.             'onepkg' => 'application/onenote',
  2003.             'csv' => 'text/csv',
  2004.         );
  2005.  
  2006.     }
  2007.  
  2008.     /**
  2009.      * Constructor, for PHP5+
  2010.      */
  2011.     function  __construct($file, $lang = 'en_GB')  {
  2012.         $this->upload($file, $lang);
  2013.     }
  2014.  
  2015.     /**
  2016.      * Constructor, for PHP4. Checks if the file has been uploaded
  2017.      *
  2018.      * The constructor takes $_FILES['form_field'] array as argument
  2019.      * where form_field is the form field name
  2020.      *
  2021.      * The constructor will check if the file has been uploaded in its temporary location, and
  2022.      * accordingly will set {@link uploaded} (and {@link error} is an error occurred)
  2023.      *
  2024.      * If the file has been uploaded, the constructor will populate all the variables holding the upload
  2025.      * information (none of the processing class variables are used here).
  2026.      * You can have access to information about the file (name, size, MIME type...).
  2027.      *
  2028.      *
  2029.      * Alternatively, you can set the first argument to be a local filename (string)
  2030.      * This allows processing of a local file, as if the file was uploaded
  2031.      *
  2032.      * The optional second argument allows you to set the language for the error messages
  2033.      *
  2034.      * @access private
  2035.      * @param  array  $file $_FILES['form_field']
  2036.      *    or   string $file Local filename
  2037.      * @param  string $lang Optional language code
  2038.      */
  2039.     function upload($file, $lang = 'en_GB') {
  2040.  
  2041.         $this->version            = '0.34dev';
  2042.  
  2043.         $this->file_src_name      = '';
  2044.         $this->file_src_name_body = '';
  2045.         $this->file_src_name_ext  = '';
  2046.         $this->file_src_mime      = '';
  2047.         $this->file_src_size      = '';
  2048.         $this->file_src_error     = '';
  2049.         $this->file_src_pathname  = '';
  2050.         $this->file_src_temp      = '';
  2051.  
  2052.         $this->file_dst_path      = '';
  2053.         $this->file_dst_name      = '';
  2054.         $this->file_dst_name_body = '';
  2055.         $this->file_dst_name_ext  = '';
  2056.         $this->file_dst_pathname  = '';
  2057.  
  2058.         $this->image_src_x        = null;
  2059.         $this->image_src_y        = null;
  2060.         $this->image_src_bits     = null;
  2061.         $this->image_src_type     = null;
  2062.         $this->image_src_pixels   = null;
  2063.         $this->image_dst_x        = 0;
  2064.         $this->image_dst_y        = 0;
  2065.         $this->image_dst_type     = '';
  2066.  
  2067.         $this->uploaded           = true;
  2068.         $this->no_upload_check    = false;
  2069.         $this->processed          = true;
  2070.         $this->error              = '';
  2071.         $this->log                = '';
  2072.         $this->allowed            = array();
  2073.         $this->forbidden          = array();
  2074.         $this->file_is_image      = false;
  2075.         $this->init();
  2076.         $info                     = null;
  2077.         $mime_from_browser        = null;
  2078.  
  2079.         // sets default language
  2080.         $this->translation        = array();
  2081.         $this->translation['file_error']                  = 'File error. Please try again.';
  2082.         $this->translation['local_file_missing']          = 'Local file doesn\'t exist.';
  2083.         $this->translation['local_file_not_readable']     = 'Local file is not readable.';
  2084.         $this->translation['uploaded_too_big_ini']        = 'File upload error (the uploaded file exceeds the upload_max_filesize directive in php.ini).';
  2085.         $this->translation['uploaded_too_big_html']       = 'File upload error (the uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form).';
  2086.         $this->translation['uploaded_partial']            = 'File upload error (the uploaded file was only partially uploaded).';
  2087.         $this->translation['uploaded_missing']            = 'File upload error (no file was uploaded).';
  2088.         $this->translation['uploaded_no_tmp_dir']         = 'File upload error (missing a temporary folder).';
  2089.         $this->translation['uploaded_cant_write']         = 'File upload error (failed to write file to disk).';
  2090.         $this->translation['uploaded_err_extension']      = 'File upload error (file upload stopped by extension).';
  2091.         $this->translation['uploaded_unknown']            = 'File upload error (unknown error code).';
  2092.         $this->translation['try_again']                   = 'File upload error. Please try again.';
  2093.         $this->translation['file_too_big']                = 'File too big.';
  2094.         $this->translation['no_mime']                     = 'MIME type can\'t be detected.';
  2095.         $this->translation['incorrect_file']              = 'Incorrect type of file.';
  2096.         $this->translation['image_too_wide']              = 'Image too wide.';
  2097.         $this->translation['image_too_narrow']            = 'Image too narrow.';
  2098.         $this->translation['image_too_high']              = 'Image too tall.';
  2099.         $this->translation['image_too_short']             = 'Image too short.';
  2100.         $this->translation['ratio_too_high']              = 'Image ratio too high (image too wide).';
  2101.         $this->translation['ratio_too_low']               = 'Image ratio too low (image too high).';
  2102.         $this->translation['too_many_pixels']             = 'Image has too many pixels.';
  2103.         $this->translation['not_enough_pixels']           = 'Image has not enough pixels.';
  2104.         $this->translation['file_not_uploaded']           = 'File not uploaded. Can\'t carry on a process.';
  2105.         $this->translation['already_exists']              = '%s already exists. Please change the file name.';
  2106.         $this->translation['temp_file_missing']           = 'No correct temp source file. Can\'t carry on a process.';
  2107.         $this->translation['source_missing']              = 'No correct uploaded source file. Can\'t carry on a process.';
  2108.         $this->translation['destination_dir']             = 'Destination directory can\'t be created. Can\'t carry on a process.';
  2109.         $this->translation['destination_dir_missing']     = 'Destination directory doesn\'t exist. Can\'t carry on a process.';
  2110.         $this->translation['destination_path_not_dir']    = 'Destination path is not a directory. Can\'t carry on a process.';
  2111.         $this->translation['destination_dir_write']       = 'Destination directory can\'t be made writeable. Can\'t carry on a process.';
  2112.         $this->translation['destination_path_write']      = 'Destination path is not a writeable. Can\'t carry on a process.';
  2113.         $this->translation['temp_file']                   = 'Can\'t create the temporary file. Can\'t carry on a process.';
  2114.         $this->translation['source_not_readable']         = 'Source file is not readable. Can\'t carry on a process.';
  2115.         $this->translation['no_create_support']           = 'No create from %s support.';
  2116.         $this->translation['create_error']                = 'Error in creating %s image from source.';
  2117.         $this->translation['source_invalid']              = 'Can\'t read image source. Not an image?.';
  2118.         $this->translation['gd_missing']                  = 'GD doesn\'t seem to be present.';
  2119.         $this->translation['watermark_no_create_support'] = 'No create from %s support, can\'t read watermark.';
  2120.         $this->translation['watermark_create_error']      = 'No %s read support, can\'t create watermark.';
  2121.         $this->translation['watermark_invalid']           = 'Unknown image format, can\'t read watermark.';
  2122.         $this->translation['file_create']                 = 'No %s create support.';
  2123.         $this->translation['no_conversion_type']          = 'No conversion type defined.';
  2124.         $this->translation['copy_failed']                 = 'Error copying file on the server. copy() failed.';
  2125.         $this->translation['reading_failed']              = 'Error reading the file.';
  2126.  
  2127.         // determines the language
  2128.         $this->lang               = $lang;
  2129.         if ($this->lang != 'en_GB' && file_exists(dirname(__FILE__).'/lang') && file_exists(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php')) {
  2130.             $translation = null;
  2131.             include(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php');
  2132.             if (is_array($translation)) {
  2133.                 $this->translation = array_merge($this->translation, $translation);
  2134.             } else {
  2135.                 $this->lang = 'en_GB';
  2136.             }
  2137.         }
  2138.  
  2139.  
  2140.         // determines the supported MIME types, and matching image format
  2141.         $this->image_supported = array();
  2142.         if ($this->gdversion()) {
  2143.             if (imagetypes() & IMG_GIF) {
  2144.                 $this->image_supported['image/gif'] = 'gif';
  2145.             }
  2146.             if (imagetypes() & IMG_JPG) {
  2147.                 $this->image_supported['image/jpg'] = 'jpg';
  2148.                 $this->image_supported['image/jpeg'] = 'jpg';
  2149.                 $this->image_supported['image/pjpeg'] = 'jpg';
  2150.             }
  2151.             if (imagetypes() & IMG_PNG) {
  2152.                 $this->image_supported['image/png'] = 'png';
  2153.                 $this->image_supported['image/x-png'] = 'png';
  2154.             }
  2155.             if (imagetypes() & IMG_WBMP) {
  2156.                 $this->image_supported['image/bmp'] = 'bmp';
  2157.                 $this->image_supported['image/x-ms-bmp'] = 'bmp';
  2158.                 $this->image_supported['image/x-windows-bmp'] = 'bmp';
  2159.             }
  2160.         }
  2161.  
  2162.         // display some system information
  2163.         if (empty($this->log)) {
  2164.             $this->log .= '<b>system information</b><br />';
  2165.             if ($this->function_enabled('ini_get_all')) {
  2166.                 $inis = ini_get_all();
  2167.                 $open_basedir = (array_key_exists('open_basedir', $inis) && array_key_exists('local_value', $inis['open_basedir']) && !empty($inis['open_basedir']['local_value'])) ? $inis['open_basedir']['local_value'] : false;
  2168.             } else {
  2169.                 $open_basedir = false;
  2170.             }
  2171.             $gd           = $this->gdversion() ? $this->gdversion(true) : 'GD not present';
  2172.             $supported    = trim((in_array('png', $this->image_supported) ? 'png' : '') . ' ' . (in_array('jpg', $this->image_supported) ? 'jpg' : '') . ' ' . (in_array('gif', $this->image_supported) ? 'gif' : '') . ' ' . (in_array('bmp', $this->image_supported) ? 'bmp' : ''));
  2173.             $this->log .= '-&nbsp;class version           : ' . $this->version . '<br />';
  2174.             $this->log .= '-&nbsp;operating system        : ' . PHP_OS . '<br />';
  2175.             $this->log .= '-&nbsp;PHP version             : ' . PHP_VERSION . '<br />';
  2176.             $this->log .= '-&nbsp;GD version              : ' . $gd . '<br />';
  2177.             $this->log .= '-&nbsp;supported image types   : ' . (!empty($supported) ? $supported : 'none') . '<br />';
  2178.             $this->log .= '-&nbsp;open_basedir            : ' . (!empty($open_basedir) ? $open_basedir : 'no restriction') . '<br />';
  2179.             $this->log .= '-&nbsp;upload_max_filesize     : ' . $this->file_max_size_raw . ' (' . $this->file_max_size . ' bytes)<br />';
  2180.             $this->log .= '-&nbsp;language                : ' . $this->lang . '<br />';
  2181.         }
  2182.  
  2183.         if (!$file) {
  2184.             $this->uploaded = false;
  2185.             $this->error = $this->translate('file_error');
  2186.         }
  2187.  
  2188.         // check if we sent a local filename or a PHP stream rather than a $_FILE element
  2189.         if (!is_array($file)) {
  2190.             if (empty($file)) {
  2191.                 $this->uploaded = false;
  2192.                 $this->error = $this->translate('file_error');
  2193.             } else {
  2194.                 if (substr($file, 0, 4) == 'php:' || substr($file, 0, 5) == 'data:' || substr($file, 0, 7) == 'base64:') {
  2195.                     $data = null;
  2196.  
  2197.                     // this is a PHP stream, i.e.not uploaded
  2198.                     if (substr($file, 0, 4) == 'php:') {
  2199.                         $file = preg_replace('/^php:(.*)/i', '$1', $file);
  2200.                         if (!$file) $file = $_SERVER['HTTP_X_FILE_NAME'];
  2201.                         if (!$file) $file = 'unknown';
  2202.                         $data = file_get_contents('php://input');
  2203.                         $this->log .= '<b>source is a PHP stream ' . $file . ' of length ' . strlen($data) . '</b><br />';
  2204.  
  2205.                     // this is the raw file data, i.e.not uploaded
  2206.                     } else if (substr($file, 0, 5) == 'data:') {
  2207.                         $data = preg_replace('/^data:(.*)/i', '$1', $file);
  2208.                         $file = 'data';
  2209.                         $this->log .= '<b>source is a data string of length ' . strlen($data) . '</b><br />';
  2210.  
  2211.                     // this is the raw file data, base64-encoded, i.e.not uploaded
  2212.                     } else if (substr($file, 0, 7) == 'base64:') {
  2213.                         $data = base64_decode(preg_replace('/^base64:(.*)/i', '$1', $file));
  2214.                         $file = 'base64';
  2215.                         $this->log .= '<b>source is a base64 data string of length ' . strlen($data) . '</b><br />';
  2216.                     }
  2217.  
  2218.                     $this->no_upload_check = TRUE;
  2219.                     $this->log .= '- requires a temp file ... ';
  2220.                     $hash = $this->temp_dir() . md5($file . rand(1, 1000));
  2221.                     if ($data && file_put_contents($hash, $data)) {
  2222.                         $this->file_src_pathname = $hash;
  2223.                         $this->log .= ' file created<br />';
  2224.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;temp file is: ' . $this->file_src_pathname . '<br />';
  2225.                     } else {
  2226.                         $this->log .= ' failed<br />';
  2227.                         $this->uploaded = false;
  2228.                         $this->error = $this->translate('temp_file');
  2229.                     }
  2230.  
  2231.                     if ($this->uploaded) {
  2232.                         $this->file_src_name       = $file;
  2233.                         $this->log .= '- local file OK<br />';
  2234.                         preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
  2235.                         if (is_array($extension) && sizeof($extension) > 0) {
  2236.                             $this->file_src_name_ext      = strtolower($extension[1]);
  2237.                             $this->file_src_name_body     = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
  2238.                         } else {
  2239.                             $this->file_src_name_ext      = '';
  2240.                             $this->file_src_name_body     = $this->file_src_name;
  2241.                         }
  2242.                         $this->file_src_size = (file_exists($this->file_src_pathname) ? filesize($this->file_src_pathname) : 0);
  2243.                     }
  2244.                     $this->file_src_error = 0;
  2245.  
  2246.                 } else {
  2247.                     // this is a local filename, i.e.not uploaded
  2248.                     $this->log .= '<b>source is a local file ' . $file . '</b><br />';
  2249.                     $this->no_upload_check = TRUE;
  2250.  
  2251.                     if ($this->uploaded && !file_exists($file)) {
  2252.                         $this->uploaded = false;
  2253.                         $this->error = $this->translate('local_file_missing');
  2254.                     }
  2255.  
  2256.                     if ($this->uploaded && !is_readable($file)) {
  2257.                         $this->uploaded = false;
  2258.                         $this->error = $this->translate('local_file_not_readable');
  2259.                     }
  2260.  
  2261.                     if ($this->uploaded) {
  2262.                         $this->file_src_pathname   = $file;
  2263.                         $this->file_src_name       = basename($file);
  2264.                         $this->log .= '- local file OK<br />';
  2265.                         preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
  2266.                         if (is_array($extension) && sizeof($extension) > 0) {
  2267.                             $this->file_src_name_ext      = strtolower($extension[1]);
  2268.                             $this->file_src_name_body     = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
  2269.                         } else {
  2270.                             $this->file_src_name_ext      = '';
  2271.                             $this->file_src_name_body     = $this->file_src_name;
  2272.                         }
  2273.                         $this->file_src_size = (file_exists($this->file_src_pathname) ? filesize($this->file_src_pathname) : 0);
  2274.                     }
  2275.                     $this->file_src_error = 0;
  2276.                 }
  2277.             }
  2278.         } else {
  2279.             // this is an element from $_FILE, i.e. an uploaded file
  2280.             $this->log .= '<b>source is an uploaded file</b><br />';
  2281.             if ($this->uploaded) {
  2282.                 $this->file_src_error         = trim($file['error']);
  2283.                 switch($this->file_src_error) {
  2284.                     case UPLOAD_ERR_OK:
  2285.                         // all is OK
  2286.                         $this->log .= '- upload OK<br />';
  2287.                         break;
  2288.                     case UPLOAD_ERR_INI_SIZE:
  2289.                         $this->uploaded = false;
  2290.                         $this->error = $this->translate('uploaded_too_big_ini');
  2291.                         break;
  2292.                     case UPLOAD_ERR_FORM_SIZE:
  2293.                         $this->uploaded = false;
  2294.                         $this->error = $this->translate('uploaded_too_big_html');
  2295.                         break;
  2296.                     case UPLOAD_ERR_PARTIAL:
  2297.                         $this->uploaded = false;
  2298.                         $this->error = $this->translate('uploaded_partial');
  2299.                         break;
  2300.                     case UPLOAD_ERR_NO_FILE:
  2301.                         $this->uploaded = false;
  2302.                         $this->error = $this->translate('uploaded_missing');
  2303.                         break;
  2304.                     case @UPLOAD_ERR_NO_TMP_DIR:
  2305.                         $this->uploaded = false;
  2306.                         $this->error = $this->translate('uploaded_no_tmp_dir');
  2307.                         break;
  2308.                     case @UPLOAD_ERR_CANT_WRITE:
  2309.                         $this->uploaded = false;
  2310.                         $this->error = $this->translate('uploaded_cant_write');
  2311.                         break;
  2312.                     case @UPLOAD_ERR_EXTENSION:
  2313.                         $this->uploaded = false;
  2314.                         $this->error = $this->translate('uploaded_err_extension');
  2315.                         break;
  2316.                     default:
  2317.                         $this->uploaded = false;
  2318.                         $this->error = $this->translate('uploaded_unknown') . ' ('.$this->file_src_error.')';
  2319.                 }
  2320.             }
  2321.  
  2322.             if ($this->uploaded) {
  2323.                 $this->file_src_pathname   = $file['tmp_name'];
  2324.                 $this->file_src_name       = $file['name'];
  2325.                 if ($this->file_src_name == '') {
  2326.                     $this->uploaded = false;
  2327.                     $this->error = $this->translate('try_again');
  2328.                 }
  2329.             }
  2330.  
  2331.             if ($this->uploaded) {
  2332.                 $this->log .= '- file name OK<br />';
  2333.                 preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
  2334.                 if (is_array($extension) && sizeof($extension) > 0) {
  2335.                     $this->file_src_name_ext      = strtolower($extension[1]);
  2336.                     $this->file_src_name_body     = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
  2337.                 } else {
  2338.                     $this->file_src_name_ext      = '';
  2339.                     $this->file_src_name_body     = $this->file_src_name;
  2340.                 }
  2341.                 $this->file_src_size = $file['size'];
  2342.                 $mime_from_browser = $file['type'];
  2343.             }
  2344.         }
  2345.  
  2346.         if ($this->uploaded) {
  2347.             $this->log .= '<b>determining MIME type</b><br />';
  2348.             $this->file_src_mime = null;
  2349.  
  2350.             // checks MIME type with Fileinfo PECL extension
  2351.             if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
  2352.                 if ($this->mime_fileinfo) {
  2353.                     $this->log .= '- Checking MIME type with Fileinfo PECL extension<br />';
  2354.                     if ($this->function_enabled('finfo_open')) {
  2355.                         $path = null;
  2356.                         if ($this->mime_fileinfo !== '') {
  2357.                             if ($this->mime_fileinfo === true) {
  2358.                                 if (getenv('MAGIC') === FALSE) {
  2359.                                     if (substr(PHP_OS, 0, 3) == 'WIN') {
  2360.                                         $path = realpath(ini_get('extension_dir') . '/../') . '/extras/magic';
  2361.                                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path defaults to ' . $path . '<br />';
  2362.                                     }
  2363.                                 } else {
  2364.                                     $path = getenv('MAGIC');
  2365.                                     $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path is set to ' . $path . ' from MAGIC variable<br />';
  2366.                                 }
  2367.                             } else {
  2368.                                 $path = $this->mime_fileinfo;
  2369.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path is set to ' . $path . '<br />';
  2370.                             }
  2371.                         }
  2372.                         if ($path) {
  2373.                             $f = @finfo_open(FILEINFO_MIME, $path);
  2374.                         } else {
  2375.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path will not be used<br />';
  2376.                             $f = @finfo_open(FILEINFO_MIME);
  2377.                         }
  2378.                         if (is_resource($f)) {
  2379.                             $mime = finfo_file($f, realpath($this->file_src_pathname));
  2380.                             finfo_close($f);
  2381.                             $this->file_src_mime = $mime;
  2382.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension<br />';
  2383.                             if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
  2384.                                 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
  2385.                                 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
  2386.                             } else {
  2387.                                 $this->file_src_mime = null;
  2388.                             }
  2389.                         } else {
  2390.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension failed (finfo_open)<br />';
  2391.                         }
  2392.                     } elseif (@class_exists('finfo')) {
  2393.                         $f = new finfo( FILEINFO_MIME );
  2394.                         if ($f) {
  2395.                             $this->file_src_mime = $f->file(realpath($this->file_src_pathname));
  2396.                             $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension<br />';
  2397.                             if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
  2398.                                 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
  2399.                                 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
  2400.                             } else {
  2401.                                 $this->file_src_mime = null;
  2402.                             }
  2403.                         } else {
  2404.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension failed (finfo)<br />';
  2405.                         }
  2406.                     } else {
  2407.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension not available<br />';
  2408.                     }
  2409.                 } else {
  2410.                     $this->log .= '- Fileinfo PECL extension deactivated<br />';
  2411.                 }
  2412.             }
  2413.  
  2414.             // checks MIME type with shell if unix access is authorized
  2415.             if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
  2416.                 if ($this->mime_file) {
  2417.                     $this->log .= '- Checking MIME type with UNIX file() command<br />';
  2418.                     if (substr(PHP_OS, 0, 3) != 'WIN') {
  2419.                         if ($this->function_enabled('exec') && $this->function_enabled('escapeshellarg')) {
  2420.                             if (strlen($mime = @exec("file -bi ".escapeshellarg($this->file_src_pathname))) != 0) {
  2421.                                 $this->file_src_mime = trim($mime);
  2422.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by UNIX file() command<br />';
  2423.                                 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
  2424.                                     $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
  2425.                                     $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
  2426.                                 } else {
  2427.                                     $this->file_src_mime = null;
  2428.                                 }
  2429.                             } else {
  2430.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;UNIX file() command failed<br />';
  2431.                             }
  2432.                         } else {
  2433.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;PHP exec() function is disabled<br />';
  2434.                         }
  2435.                     } else {
  2436.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;UNIX file() command not availabled<br />';
  2437.                     }
  2438.                 } else {
  2439.                     $this->log .= '- UNIX file() command is deactivated<br />';
  2440.                 }
  2441.             }
  2442.  
  2443.             // checks MIME type with mime_magic
  2444.             if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
  2445.                 if ($this->mime_magic) {
  2446.                     $this->log .= '- Checking MIME type with mime.magic file (mime_content_type())<br />';
  2447.                     if ($this->function_enabled('mime_content_type')) {
  2448.                         $this->file_src_mime = mime_content_type($this->file_src_pathname);
  2449.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by mime_content_type()<br />';
  2450.                         if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
  2451.                             $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
  2452.                             $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
  2453.                         } else {
  2454.                             $this->file_src_mime = null;
  2455.                         }
  2456.                     } else {
  2457.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;mime_content_type() is not available<br />';
  2458.                     }
  2459.                 } else {
  2460.                     $this->log .= '- mime.magic file (mime_content_type()) is deactivated<br />';
  2461.                 }
  2462.             }
  2463.  
  2464.             // checks MIME type with getimagesize()
  2465.             if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
  2466.                 if ($this->mime_getimagesize) {
  2467.                     $this->log .= '- Checking MIME type with getimagesize()<br />';
  2468.                     $info = getimagesize($this->file_src_pathname);
  2469.                     if (is_array($info) && array_key_exists('mime', $info)) {
  2470.                         $this->file_src_mime = trim($info['mime']);
  2471.                         if (empty($this->file_src_mime)) {
  2472.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME empty, guessing from type<br />';
  2473.                             $mime = (is_array($info) && array_key_exists(2, $info) ? $info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG
  2474.                             $this->file_src_mime = ($mime==IMAGETYPE_GIF ? 'image/gif' : ($mime==IMAGETYPE_JPEG ? 'image/jpeg' : ($mime==IMAGETYPE_PNG ? 'image/png' : ($mime==IMAGETYPE_BMP ? 'image/bmp' : null))));
  2475.                         }
  2476.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by PHP getimagesize() function<br />';
  2477.                         if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
  2478.                             $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
  2479.                             $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
  2480.                         } else {
  2481.                             $this->file_src_mime = null;
  2482.                         }
  2483.                     } else {
  2484.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;getimagesize() failed<br />';
  2485.                     }
  2486.                 } else {
  2487.                     $this->log .= '- getimagesize() is deactivated<br />';
  2488.                 }
  2489.             }
  2490.  
  2491.             // default to MIME from browser (or Flash)
  2492.             if (!empty($mime_from_browser) && !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime)) {
  2493.                 $this->file_src_mime =$mime_from_browser;
  2494.                 $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by browser<br />';
  2495.                 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
  2496.                     $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
  2497.                     $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
  2498.                 } else {
  2499.                     $this->file_src_mime = null;
  2500.                 }
  2501.             }
  2502.  
  2503.             // we need to work some magic if we upload via Flash
  2504.             if ($this->file_src_mime == 'application/octet-stream' || !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
  2505.                 if ($this->file_src_mime == 'application/octet-stream') $this->log .= '- Flash may be rewriting MIME as application/octet-stream<br />';
  2506.                 $this->log .= '- Try to guess MIME type from file extension (' . $this->file_src_name_ext . '): ';
  2507.                 if (array_key_exists($this->file_src_name_ext, $this->mime_types)) $this->file_src_mime = $this->mime_types[$this->file_src_name_ext];
  2508.                 if ($this->file_src_mime == 'application/octet-stream') {
  2509.                     $this->log .= 'doesn\'t look like anything known<br />';
  2510.                 } else {
  2511.                     $this->log .= 'MIME type set to ' . $this->file_src_mime . '<br />';
  2512.                 }
  2513.             }
  2514.  
  2515.             if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) {
  2516.                 $this->log .= '- MIME type couldn\'t be detected! (' . (string) $this->file_src_mime . ')<br />';
  2517.             }
  2518.  
  2519.             // determine whether the file is an image
  2520.             if ($this->file_src_mime && is_string($this->file_src_mime) && !empty($this->file_src_mime) && array_key_exists($this->file_src_mime, $this->image_supported)) {
  2521.                 $this->file_is_image = true;
  2522.                 $this->image_src_type = $this->image_supported[$this->file_src_mime];
  2523.             }
  2524.  
  2525.             // if the file is an image, we gather some useful data
  2526.             if ($this->file_is_image) {
  2527.                 if ($h = fopen($this->file_src_pathname, 'r')) {
  2528.                     fclose($h);
  2529.                     $info = getimagesize($this->file_src_pathname);
  2530.                     if (is_array($info)) {
  2531.                         $this->image_src_x    = $info[0];
  2532.                         $this->image_src_y    = $info[1];
  2533.                         $this->image_dst_x    = $this->image_src_x;
  2534.                         $this->image_dst_y    = $this->image_src_y;
  2535.                         $this->image_src_pixels = $this->image_src_x * $this->image_src_y;
  2536.                         $this->image_src_bits = array_key_exists('bits', $info) ? $info['bits'] : null;
  2537.                     } else {
  2538.                         $this->file_is_image = false;
  2539.                         $this->uploaded = false;
  2540.                         $this->log .= '- can\'t retrieve image information, image may have been tampered with<br />';
  2541.                         $this->error = $this->translate('source_invalid');
  2542.                     }
  2543.                 } else {
  2544.                     $this->log .= '- can\'t read source file directly. open_basedir restriction in place?<br />';
  2545.                 }
  2546.             }
  2547.  
  2548.             $this->log .= '<b>source variables</b><br />';
  2549.             $this->log .= '- You can use all these before calling process()<br />';
  2550.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name         : ' . $this->file_src_name . '<br />';
  2551.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name_body    : ' . $this->file_src_name_body . '<br />';
  2552.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name_ext     : ' . $this->file_src_name_ext . '<br />';
  2553.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_pathname     : ' . $this->file_src_pathname . '<br />';
  2554.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_mime         : ' . $this->file_src_mime . '<br />';
  2555.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_size         : ' . $this->file_src_size . ' (max= ' . $this->file_max_size . ')<br />';
  2556.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_error        : ' . $this->file_src_error . '<br />';
  2557.  
  2558.             if ($this->file_is_image) {
  2559.                 $this->log .= '- source file is an image<br />';
  2560.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_x           : ' . $this->image_src_x . '<br />';
  2561.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_y           : ' . $this->image_src_y . '<br />';
  2562.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_pixels      : ' . $this->image_src_pixels . '<br />';
  2563.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_type        : ' . $this->image_src_type . '<br />';
  2564.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_bits        : ' . $this->image_src_bits . '<br />';
  2565.             }
  2566.         }
  2567.  
  2568.     }
  2569.  
  2570.     /**
  2571.      * Returns the version of GD
  2572.      *
  2573.      * @access public
  2574.      * @param  boolean  $full Optional flag to get precise version
  2575.      * @return float GD version
  2576.      */
  2577.     function gdversion($full = false) {
  2578.         static $gd_version = null;
  2579.         static $gd_full_version = null;
  2580.         if ($gd_version === null) {
  2581.             if ($this->function_enabled('gd_info')) {
  2582.                 $gd = gd_info();
  2583.                 $gd = $gd["GD Version"];
  2584.                 $regex = "/([\d\.]+)/i";
  2585.             } else {
  2586.                 ob_start();
  2587.                 phpinfo(8);
  2588.                 $gd = ob_get_contents();
  2589.                 ob_end_clean();
  2590.                 $regex = "/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i";
  2591.             }
  2592.             if (preg_match($regex, $gd, $m)) {
  2593.                 $gd_full_version = (string) $m[1];
  2594.                 $gd_version = (float) $m[1];
  2595.             } else {
  2596.                 $gd_full_version = 'none';
  2597.                 $gd_version = 0;
  2598.             }
  2599.         }
  2600.         if ($full) {
  2601.             return $gd_full_version;
  2602.         } else {
  2603.             return $gd_version;
  2604.         }
  2605.     }
  2606.  
  2607.     /**
  2608.      * Checks if a function is available
  2609.      *
  2610.      * @access private
  2611.      * @param  string  $func Function name
  2612.      * @return boolean Success
  2613.      */
  2614.     function function_enabled($func) {
  2615.         // cache the list of disabled functions
  2616.         static $disabled = null;
  2617.         if ($disabled === null) $disabled = array_map('trim', array_map('strtolower', explode(',', ini_get('disable_functions'))));
  2618.         // cache the list of functions blacklisted by suhosin
  2619.         static $blacklist = null;
  2620.         if ($blacklist === null) $blacklist = extension_loaded('suhosin') ? array_map('trim', array_map('strtolower', explode(',', ini_get('  suhosin.executor.func.blacklist')))) : array();
  2621.         // checks if the function is really enabled
  2622.         return (function_exists($func) && !in_array($func, $disabled) && !in_array($func, $blacklist));
  2623.     }
  2624.  
  2625.     /**
  2626.      * Creates directories recursively
  2627.      *
  2628.      * @access private
  2629.      * @param  string  $path Path to create
  2630.      * @param  integer $mode Optional permissions
  2631.      * @return boolean Success
  2632.      */
  2633.     function rmkdir($path, $mode = 0777) {
  2634.         return is_dir($path) || ( $this->rmkdir(dirname($path), $mode) && $this->_mkdir($path, $mode) );
  2635.     }
  2636.  
  2637.     /**
  2638.      * Creates directory
  2639.      *
  2640.      * @access private
  2641.      * @param  string  $path Path to create
  2642.      * @param  integer $mode Optional permissions
  2643.      * @return boolean Success
  2644.      */
  2645.     function _mkdir($path, $mode = 0777) {
  2646.         $old = umask(0);
  2647.         $res = @mkdir($path, $mode);
  2648.         umask($old);
  2649.         return $res;
  2650.     }
  2651.  
  2652.     /**
  2653.      * Translate error messages
  2654.      *
  2655.      * @access private
  2656.      * @param  string  $str    Message to translate
  2657.      * @param  array   $tokens Optional token values
  2658.      * @return string Translated string
  2659.      */
  2660.     function translate($str, $tokens = array()) {
  2661.         if (array_key_exists($str, $this->translation)) $str = $this->translation[$str];
  2662.         if (is_array($tokens) && sizeof($tokens) > 0)   $str = vsprintf($str, $tokens);
  2663.         return $str;
  2664.     }
  2665.  
  2666.     /**
  2667.      * Returns the temp directory
  2668.      *
  2669.      * @access private
  2670.      * @return string Temp directory string
  2671.      */
  2672.     function temp_dir() {
  2673.         $dir = '';
  2674.         if ($this->function_enabled('sys_get_temp_dir')) $dir = sys_get_temp_dir();
  2675.         if (!$dir && $tmp=getenv('TMP'))    $dir = $tmp;
  2676.         if (!$dir && $tmp=getenv('TEMP'))   $dir = $tmp;
  2677.         if (!$dir && $tmp=getenv('TMPDIR')) $dir = $tmp;
  2678.         if (!$dir) {
  2679.             $tmp = tempnam(__FILE__,'');
  2680.             if (file_exists($tmp)) {
  2681.                 unlink($tmp);
  2682.                 $dir = dirname($tmp);
  2683.             }
  2684.         }
  2685.         if (!$dir) return '';
  2686.         $slash = (strtolower(substr(PHP_OS, 0, 3)) === 'win' ? '\\' : '/');
  2687.         if (substr($dir, -1) != $slash) $dir = $dir . $slash;
  2688.         return $dir;
  2689.     }
  2690.  
  2691.     /**
  2692.      * Decodes colors
  2693.      *
  2694.      * @access private
  2695.      * @param  string  $color  Color string
  2696.      * @return array RGB colors
  2697.      */
  2698.     function getcolors($color) {
  2699.         $color = str_replace('#', '', $color);
  2700.         if (strlen($color) == 3) $color = str_repeat(substr($color, 0, 1), 2) . str_repeat(substr($color, 1, 1), 2) . str_repeat(substr($color, 2, 1), 2);
  2701.         $r = sscanf($color, "%2x%2x%2x");
  2702.         $red   = (is_array($r) && array_key_exists(0, $r) && is_numeric($r[0]) ? $r[0] : 0);
  2703.         $green = (is_array($r) && array_key_exists(1, $r) && is_numeric($r[1]) ? $r[1] : 0);
  2704.         $blue  = (is_array($r) && array_key_exists(2, $r) && is_numeric($r[2]) ? $r[2] : 0);
  2705.         return array($red, $green, $blue);
  2706.     }
  2707.  
  2708.     /**
  2709.      * Decodes sizes
  2710.      *
  2711.      * @access private
  2712.      * @param  string  $size  Size in bytes, or shorthand byte options
  2713.      * @return integer Size in bytes
  2714.      */
  2715.     function getsize($size) {
  2716.         if ($size === null) return null;
  2717.         $last = strtolower($size{strlen($size)-1});
  2718.         $size = (int) $size;
  2719.         switch($last) {
  2720.             case 'g':
  2721.                 $size *= 1024;
  2722.             case 'm':
  2723.                 $size *= 1024;
  2724.             case 'k':
  2725.                 $size *= 1024;
  2726.         }
  2727.         return $size;
  2728.     }
  2729.  
  2730.     /**
  2731.      * Decodes offsets
  2732.      *
  2733.      * @access private
  2734.      * @param  misc    $offsets  Offsets, as an integer, a string or an array
  2735.      * @param  integer $x        Reference picture width
  2736.      * @param  integer $y        Reference picture height
  2737.      * @param  boolean $round    Round offsets before returning them
  2738.      * @param  boolean $negative Allow negative offsets to be returned
  2739.      * @return array Array of four offsets (TRBL)
  2740.      */
  2741.     function getoffsets($offsets, $x, $y, $round = true, $negative = true) {
  2742.         if (!is_array($offsets)) $offsets = explode(' ', $offsets);
  2743.         if (sizeof($offsets) == 4) {
  2744.              $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[2]; $cl = $offsets[3];
  2745.         } else if (sizeof($offsets) == 2) {
  2746.             $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[0]; $cl = $offsets[1];
  2747.         } else {
  2748.             $ct = $offsets[0]; $cr = $offsets[0]; $cb = $offsets[0]; $cl = $offsets[0];
  2749.         }
  2750.         if (strpos($ct, '%')>0) $ct = $y * (str_replace('%','',$ct) / 100);
  2751.         if (strpos($cr, '%')>0) $cr = $x * (str_replace('%','',$cr) / 100);
  2752.         if (strpos($cb, '%')>0) $cb = $y * (str_replace('%','',$cb) / 100);
  2753.         if (strpos($cl, '%')>0) $cl = $x * (str_replace('%','',$cl) / 100);
  2754.         if (strpos($ct, 'px')>0) $ct = str_replace('px','',$ct);
  2755.         if (strpos($cr, 'px')>0) $cr = str_replace('px','',$cr);
  2756.         if (strpos($cb, 'px')>0) $cb = str_replace('px','',$cb);
  2757.         if (strpos($cl, 'px')>0) $cl = str_replace('px','',$cl);
  2758.         $ct = (int) $ct; $cr = (int) $cr; $cb = (int) $cb; $cl = (int) $cl;
  2759.         if ($round) {
  2760.             $ct = round($ct);
  2761.             $cr = round($cr);
  2762.             $cb = round($cb);
  2763.             $cl = round($cl);
  2764.         }
  2765.         if (!$negative) {
  2766.             if ($ct < 0) $ct = 0;
  2767.             if ($cr < 0) $cr = 0;
  2768.             if ($cb < 0) $cb = 0;
  2769.             if ($cl < 0) $cl = 0;
  2770.         }
  2771.         return array($ct, $cr, $cb, $cl);
  2772.     }
  2773.  
  2774.     /**
  2775.      * Creates a container image
  2776.      *
  2777.      * @access private
  2778.      * @param  integer  $x    Width
  2779.      * @param  integer  $y    Height
  2780.      * @param  boolean  $fill Optional flag to draw the background color or not
  2781.      * @param  boolean  $trsp Optional flag to set the background to be transparent
  2782.      * @return resource Container image
  2783.      */
  2784.     function imagecreatenew($x, $y, $fill = true, $trsp = false) {
  2785.         if ($x < 1) $x = 1; if ($y < 1) $y = 1;
  2786.         if ($this->gdversion() >= 2 && !$this->image_is_palette) {
  2787.             // create a true color image
  2788.             $dst_im = imagecreatetruecolor($x, $y);
  2789.             // this preserves transparency in PNGs, in true color
  2790.             if (empty($this->image_background_color) || $trsp) {
  2791.                 imagealphablending($dst_im, false );
  2792.                 imagefilledrectangle($dst_im, 0, 0, $x, $y, imagecolorallocatealpha($dst_im, 0, 0, 0, 127));
  2793.             }
  2794.         } else {
  2795.             // creates a palette image
  2796.             $dst_im = imagecreate($x, $y);
  2797.             // preserves transparency for palette images, if the original image has transparency
  2798.             if (($fill && $this->image_is_transparent && empty($this->image_background_color)) || $trsp) {
  2799.                 imagefilledrectangle($dst_im, 0, 0, $x, $y, $this->image_transparent_color);
  2800.                 imagecolortransparent($dst_im, $this->image_transparent_color);
  2801.             }
  2802.         }
  2803.         // fills with background color if any is set
  2804.         if ($fill && !empty($this->image_background_color) && !$trsp) {
  2805.             list($red, $green, $blue) = $this->getcolors($this->image_background_color);
  2806.             $background_color = imagecolorallocate($dst_im, $red, $green, $blue);
  2807.             imagefilledrectangle($dst_im, 0, 0, $x, $y, $background_color);
  2808.         }
  2809.         return $dst_im;
  2810.     }
  2811.  
  2812.  
  2813.     /**
  2814.      * Transfers an image from the container to the destination image
  2815.      *
  2816.      * @access private
  2817.      * @param  resource $src_im Container image
  2818.      * @param  resource $dst_im Destination image
  2819.      * @return resource Destination image
  2820.      */
  2821.     function imagetransfer($src_im, $dst_im) {
  2822.         if (is_resource($dst_im)) imagedestroy($dst_im);
  2823.         $dst_im = & $src_im;
  2824.         return $dst_im;
  2825.     }
  2826.  
  2827.     /**
  2828.      * Merges two images
  2829.      *
  2830.      * If the output format is PNG, then we do it pixel per pixel to retain the alpha channel
  2831.      *
  2832.      * @access private
  2833.      * @param  resource $dst_img Destination image
  2834.      * @param  resource $src_img Overlay image
  2835.      * @param  int      $dst_x   x-coordinate of destination point
  2836.      * @param  int      $dst_y   y-coordinate of destination point
  2837.      * @param  int      $src_x   x-coordinate of source point
  2838.      * @param  int      $src_y   y-coordinate of source point
  2839.      * @param  int      $src_w   Source width
  2840.      * @param  int      $src_h   Source height
  2841.      * @param  int      $pct     Optional percentage of the overlay, between 0 and 100 (default: 100)
  2842.      * @return resource Destination image
  2843.      */
  2844.     function imagecopymergealpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct = 0) {
  2845.         $dst_x = (int) $dst_x;
  2846.         $dst_y = (int) $dst_y;
  2847.         $src_x = (int) $src_x;
  2848.         $src_y = (int) $src_y;
  2849.         $src_w = (int) $src_w;
  2850.         $src_h = (int) $src_h;
  2851.         $pct   = (int) $pct;
  2852.         $dst_w = imagesx($dst_im);
  2853.         $dst_h = imagesy($dst_im);
  2854.  
  2855.         for ($y = $src_y; $y < $src_h; $y++) {
  2856.             for ($x = $src_x; $x < $src_w; $x++) {
  2857.  
  2858.                 if ($x + $dst_x >= 0 && $x + $dst_x < $dst_w && $x + $src_x >= 0 && $x + $src_x < $src_w
  2859.                  && $y + $dst_y >= 0 && $y + $dst_y < $dst_h && $y + $src_y >= 0 && $y + $src_y < $src_h) {
  2860.  
  2861.                     $dst_pixel = imagecolorsforindex($dst_im, imagecolorat($dst_im, $x + $dst_x, $y + $dst_y));
  2862.                     $src_pixel = imagecolorsforindex($src_im, imagecolorat($src_im, $x + $src_x, $y + $src_y));
  2863.  
  2864.                     $src_alpha = 1 - ($src_pixel['alpha'] / 127);
  2865.                     $dst_alpha = 1 - ($dst_pixel['alpha'] / 127);
  2866.                     $opacity = $src_alpha * $pct / 100;
  2867.                     if ($dst_alpha >= $opacity) $alpha = $dst_alpha;
  2868.                     if ($dst_alpha < $opacity)  $alpha = $opacity;
  2869.                     if ($alpha > 1) $alpha = 1;
  2870.  
  2871.                     if ($opacity > 0) {
  2872.                         $dst_red   = round(( ($dst_pixel['red']   * $dst_alpha * (1 - $opacity)) ) );
  2873.                         $dst_green = round(( ($dst_pixel['green'] * $dst_alpha * (1 - $opacity)) ) );
  2874.                         $dst_blue  = round(( ($dst_pixel['blue']  * $dst_alpha * (1 - $opacity)) ) );
  2875.                         $src_red   = round((($src_pixel['red']   * $opacity)) );
  2876.                         $src_green = round((($src_pixel['green'] * $opacity)) );
  2877.                         $src_blue  = round((($src_pixel['blue']  * $opacity)) );
  2878.                         $red   = round(($dst_red   + $src_red  ) / ($dst_alpha * (1 - $opacity) + $opacity));
  2879.                         $green = round(($dst_green + $src_green) / ($dst_alpha * (1 - $opacity) + $opacity));
  2880.                         $blue  = round(($dst_blue  + $src_blue ) / ($dst_alpha * (1 - $opacity) + $opacity));
  2881.                         if ($red   > 255) $red   = 255;
  2882.                         if ($green > 255) $green = 255;
  2883.                         if ($blue  > 255) $blue  = 255;
  2884.                         $alpha =  round((1 - $alpha) * 127);
  2885.                         $color = imagecolorallocatealpha($dst_im, $red, $green, $blue, $alpha);
  2886.                         imagesetpixel($dst_im, $x + $dst_x, $y + $dst_y, $color);
  2887.                     }
  2888.                 }
  2889.             }
  2890.         }
  2891.         return true;
  2892.     }
  2893.  
  2894.  
  2895.  
  2896.     /**
  2897.      * Actually uploads the file, and act on it according to the set processing class variables
  2898.      *
  2899.      * This function copies the uploaded file to the given location, eventually performing actions on it.
  2900.      * Typically, you can call {@link process} several times for the same file,
  2901.      * for instance to create a resized image and a thumbnail of the same file.
  2902.      * The original uploaded file remains intact in its temporary location, so you can use {@link process} several times.
  2903.      * You will be able to delete the uploaded file with {@link clean} when you have finished all your {@link process} calls.
  2904.      *
  2905.      * According to the processing class variables set in the calling file, the file can be renamed,
  2906.      * and if it is an image, can be resized or converted.
  2907.      *
  2908.      * When the processing is completed, and the file copied to its new location, the
  2909.      * processing class variables will be reset to their default value.
  2910.      * This allows you to set new properties, and perform another {@link process} on the same uploaded file
  2911.      *
  2912.      * If the function is called with a null or empty argument, then it will return the content of the picture
  2913.      *
  2914.      * It will set {@link processed} (and {@link error} is an error occurred)
  2915.      *
  2916.      * @access public
  2917.      * @param  string $server_path Optional path location of the uploaded file, with an ending slash
  2918.      * @return string Optional content of the image
  2919.      */
  2920.     function process($server_path = null) {
  2921.         $this->error        = '';
  2922.         $this->processed    = true;
  2923.         $return_mode        = false;
  2924.         $return_content     = null;
  2925.  
  2926.         // clean up dst variables
  2927.         $this->file_dst_path        = '';
  2928.         $this->file_dst_pathname    = '';
  2929.         $this->file_dst_name        = '';
  2930.         $this->file_dst_name_body   = '';
  2931.         $this->file_dst_name_ext    = '';
  2932.  
  2933.         // clean up some parameters
  2934.         $this->file_max_size = $this->getsize($this->file_max_size);
  2935.         $this->jpeg_size = $this->getsize($this->jpeg_size);
  2936.  
  2937.         // copy some variables as we need to keep them clean
  2938.         $file_src_name = $this->file_src_name;
  2939.         $file_src_name_body = $this->file_src_name_body;
  2940.         $file_src_name_ext = $this->file_src_name_ext;
  2941.  
  2942.         if (!$this->uploaded) {
  2943.             $this->error = $this->translate('file_not_uploaded');
  2944.             $this->processed = false;
  2945.         }
  2946.  
  2947.         if ($this->processed) {
  2948.             if (empty($server_path) || is_null($server_path)) {
  2949.                 $this->log .= '<b>process file and return the content</b><br />';
  2950.                 $return_mode = true;
  2951.             } else {
  2952.                 if(strtolower(substr(PHP_OS, 0, 3)) === 'win') {
  2953.                     if (substr($server_path, -1, 1) != '\\') $server_path = $server_path . '\\';
  2954.                 } else {
  2955.                     if (substr($server_path, -1, 1) != '/') $server_path = $server_path . '/';
  2956.                 }
  2957.                 $this->log .= '<b>process file to '  . $server_path . '</b><br />';
  2958.             }
  2959.         }
  2960.  
  2961.         if ($this->processed) {
  2962.             // checks file max size
  2963.             if ($this->file_src_size > $this->file_max_size) {
  2964.                 $this->processed = false;
  2965.                 $this->error = $this->translate('file_too_big') . ' : ' . $this->file_src_size . ' > ' . $this->file_max_size;
  2966.             } else {
  2967.                 $this->log .= '- file size OK<br />';
  2968.             }
  2969.         }
  2970.  
  2971.         if ($this->processed) {
  2972.             // if we have an image without extension, set it
  2973.             if ($this->file_force_extension && $this->file_is_image && !$this->file_src_name_ext) $file_src_name_ext = $this->image_src_type;
  2974.             // turn dangerous scripts into text files
  2975.             if ($this->no_script) {
  2976.                 // if the file has no extension, we try to guess it from the MIME type
  2977.                 if ($this->file_force_extension && empty($file_src_name_ext)) {
  2978.                     if ($key = array_search($this->file_src_mime, $this->mime_types)) {
  2979.                         $file_src_name_ext = $key;
  2980.                         $file_src_name = $file_src_name_body . '.' . $file_src_name_ext;
  2981.                         $this->log .= '- file renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!<br />';
  2982.                     }
  2983.                 }
  2984.                 // if the file is text based, or has a dangerous extension, we rename it as .txt
  2985.                 if ((((substr($this->file_src_mime, 0, 5) == 'text/' && $this->file_src_mime != 'text/rtf') || strpos($this->file_src_mime, 'javascript') !== false)  && (substr($file_src_name, -4) != '.txt'))
  2986.                     || preg_match('/\.(php|php5|php4|php3|phtml|pl|py|cgi|asp|js)$/i', $this->file_src_name)
  2987.                     || $this->file_force_extension && empty($file_src_name_ext)) {
  2988.                     $this->file_src_mime = 'text/plain';
  2989.                     if ($this->file_src_name_ext) $file_src_name_body = $file_src_name_body . '.' . $this->file_src_name_ext;
  2990.                     $file_src_name_ext = 'txt';
  2991.                     $file_src_name = $file_src_name_body . '.' . $file_src_name_ext;
  2992.                     $this->log .= '- script renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!<br />';
  2993.                 }
  2994.             }
  2995.  
  2996.             if ($this->mime_check && empty($this->file_src_mime)) {
  2997.                 $this->processed = false;
  2998.                 $this->error = $this->translate('no_mime');
  2999.             } else if ($this->mime_check && !empty($this->file_src_mime) && strpos($this->file_src_mime, '/') !== false) {
  3000.                 list($m1, $m2) = explode('/', $this->file_src_mime);
  3001.                 $allowed = false;
  3002.                 // check wether the mime type is allowed
  3003.                 if (!is_array($this->allowed)) $this->allowed = array($this->allowed);
  3004.                 foreach($this->allowed as $k => $v) {
  3005.                     list($v1, $v2) = explode('/', $v);
  3006.                     if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) {
  3007.                         $allowed = true;
  3008.                         break;
  3009.                     }
  3010.                 }
  3011.                 // check wether the mime type is forbidden
  3012.                 if (!is_array($this->forbidden)) $this->forbidden = array($this->forbidden);
  3013.                 foreach($this->forbidden as $k => $v) {
  3014.                     list($v1, $v2) = explode('/', $v);
  3015.                     if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) {
  3016.                         $allowed = false;
  3017.                         break;
  3018.                     }
  3019.                 }
  3020.                 if (!$allowed) {
  3021.                     $this->processed = false;
  3022.                     $this->error = $this->translate('incorrect_file');
  3023.                 } else {
  3024.                     $this->log .= '- file mime OK : ' . $this->file_src_mime . '<br />';
  3025.                 }
  3026.             } else {
  3027.                 $this->log .= '- file mime (not checked) : ' . $this->file_src_mime . '<br />';
  3028.             }
  3029.  
  3030.             // if the file is an image, we can check on its dimensions
  3031.             // these checks are not available if open_basedir restrictions are in place
  3032.             if ($this->file_is_image) {
  3033.                 if (is_numeric($this->image_src_x) && is_numeric($this->image_src_y)) {
  3034.                     $ratio = $this->image_src_x / $this->image_src_y;
  3035.                     if (!is_null($this->image_max_width) && $this->image_src_x > $this->image_max_width) {
  3036.                         $this->processed = false;
  3037.                         $this->error = $this->translate('image_too_wide');
  3038.                     }
  3039.                     if (!is_null($this->image_min_width) && $this->image_src_x < $this->image_min_width) {
  3040.                         $this->processed = false;
  3041.                         $this->error = $this->translate('image_too_narrow');
  3042.                     }
  3043.                     if (!is_null($this->image_max_height) && $this->image_src_y > $this->image_max_height) {
  3044.                         $this->processed = false;
  3045.                         $this->error = $this->translate('image_too_high');
  3046.                     }
  3047.                     if (!is_null($this->image_min_height) && $this->image_src_y < $this->image_min_height) {
  3048.                         $this->processed = false;
  3049.                         $this->error = $this->translate('image_too_short');
  3050.                     }
  3051.                     if (!is_null($this->image_max_ratio) && $ratio > $this->image_max_ratio) {
  3052.                         $this->processed = false;
  3053.                         $this->error = $this->translate('ratio_too_high');
  3054.                     }
  3055.                     if (!is_null($this->image_min_ratio) && $ratio < $this->image_min_ratio) {
  3056.                         $this->processed = false;
  3057.                         $this->error = $this->translate('ratio_too_low');
  3058.                     }
  3059.                     if (!is_null($this->image_max_pixels) && $this->image_src_pixels > $this->image_max_pixels) {
  3060.                         $this->processed = false;
  3061.                         $this->error = $this->translate('too_many_pixels');
  3062.                     }
  3063.                     if (!is_null($this->image_min_pixels) && $this->image_src_pixels < $this->image_min_pixels) {
  3064.                         $this->processed = false;
  3065.                         $this->error = $this->translate('not_enough_pixels');
  3066.                     }
  3067.                 } else {
  3068.                     $this->log .= '- no image properties available, can\'t enforce dimension checks : ' . $this->file_src_mime . '<br />';
  3069.                 }
  3070.             }
  3071.         }
  3072.  
  3073.         if ($this->processed) {
  3074.             $this->file_dst_path        = $server_path;
  3075.  
  3076.             // repopulate dst variables from src
  3077.             $this->file_dst_name        = $file_src_name;
  3078.             $this->file_dst_name_body   = $file_src_name_body;
  3079.             $this->file_dst_name_ext    = $file_src_name_ext;
  3080.             if ($this->file_overwrite) $this->file_auto_rename = false;
  3081.  
  3082.             if ($this->image_convert && $this->file_is_image) { // if we convert as an image
  3083.                 if ($this->file_src_name_ext) $this->file_dst_name_ext  = $this->image_convert;
  3084.                 $this->log .= '- new file name ext : ' . $this->image_convert . '<br />';
  3085.             }
  3086.             if (!is_null($this->file_new_name_body)) { // rename file body
  3087.                 $this->file_dst_name_body = $this->file_new_name_body;
  3088.                 $this->log .= '- new file name body : ' . $this->file_new_name_body . '<br />';
  3089.             }
  3090.             if (!is_null($this->file_new_name_ext)) { // rename file ext
  3091.                 $this->file_dst_name_ext  = $this->file_new_name_ext;
  3092.                 $this->log .= '- new file name ext : ' . $this->file_new_name_ext . '<br />';
  3093.             }
  3094.             if (!is_null($this->file_name_body_add)) { // append a string to the name
  3095.                 $this->file_dst_name_body  = $this->file_dst_name_body . $this->file_name_body_add;
  3096.                 $this->log .= '- file name body append : ' . $this->file_name_body_add . '<br />';
  3097.             }
  3098.             if (!is_null($this->file_name_body_pre)) { // prepend a string to the name
  3099.                 $this->file_dst_name_body  = $this->file_name_body_pre . $this->file_dst_name_body;
  3100.                 $this->log .= '- file name body prepend : ' . $this->file_name_body_pre . '<br />';
  3101.             }
  3102.             if ($this->file_safe_name) { // formats the name
  3103.                 $this->file_dst_name_body = utf8_encode(strtr(utf8_decode($this->file_dst_name_body), utf8_decode('ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ'), 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'));
  3104.                 $this->file_dst_name_body = strtr($this->file_dst_name_body, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));
  3105.                 $this->file_dst_name_body = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $this->file_dst_name_body);
  3106.                 $this->log .= '- file name safe format<br />';
  3107.             }
  3108.  
  3109.             $this->log .= '- destination variables<br />';
  3110.             if (empty($this->file_dst_path) || is_null($this->file_dst_path)) {
  3111.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_path         : n/a<br />';
  3112.             } else {
  3113.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_path         : ' . $this->file_dst_path . '<br />';
  3114.             }
  3115.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name_body    : ' . $this->file_dst_name_body . '<br />';
  3116.             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name_ext     : ' . $this->file_dst_name_ext . '<br />';
  3117.  
  3118.             // set the destination file name
  3119.             $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
  3120.  
  3121.             if (!$return_mode) {
  3122.                 if (!$this->file_auto_rename) {
  3123.                     $this->log .= '- no auto_rename if same filename exists<br />';
  3124.                     $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
  3125.                 } else {
  3126.                     $this->log .= '- checking for auto_rename<br />';
  3127.                     $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
  3128.                     $body = $this->file_dst_name_body;
  3129.                     $ext = '';
  3130.                     // if we have changed the extension, then we add our increment before
  3131.                     if ($file_src_name_ext != $this->file_src_name_ext) {
  3132.                         if (substr($this->file_dst_name_body, -1 - strlen($this->file_src_name_ext)) == '.' . $this->file_src_name_ext) {
  3133.                             $body = substr($this->file_dst_name_body, 0, strlen($this->file_dst_name_body) - 1 - strlen($this->file_src_name_ext));
  3134.                             $ext = '.' . $this->file_src_name_ext;
  3135.                         }
  3136.                     }
  3137.                     $cpt = 1;
  3138.                     while (@file_exists($this->file_dst_pathname)) {
  3139.                         $this->file_dst_name_body = $body . '_' . $cpt . $ext;
  3140.                         $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
  3141.                         $cpt++;
  3142.                         $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
  3143.                     }
  3144.                     if ($cpt>1) $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;auto_rename to ' . $this->file_dst_name . '<br />';
  3145.                 }
  3146.  
  3147.                 $this->log .= '- destination file details<br />';
  3148.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name         : ' . $this->file_dst_name . '<br />';
  3149.                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_pathname     : ' . $this->file_dst_pathname . '<br />';
  3150.  
  3151.                 if ($this->file_overwrite) {
  3152.                      $this->log .= '- no overwrite checking<br />';
  3153.                 } else {
  3154.                     if (@file_exists($this->file_dst_pathname)) {
  3155.                         $this->processed = false;
  3156.                         $this->error = $this->translate('already_exists', array($this->file_dst_name));
  3157.                     } else {
  3158.                         $this->log .= '- ' . $this->file_dst_name . ' doesn\'t exist already<br />';
  3159.                     }
  3160.                 }
  3161.             }
  3162.         }
  3163.  
  3164.         if ($this->processed) {
  3165.             // if we have already moved the uploaded file, we use the temporary copy as source file, and check if it exists
  3166.             if (!empty($this->file_src_temp)) {
  3167.                 $this->log .= '- use the temp file instead of the original file since it is a second process<br />';
  3168.                 $this->file_src_pathname   = $this->file_src_temp;
  3169.                 if (!file_exists($this->file_src_pathname)) {
  3170.                     $this->processed = false;
  3171.                     $this->error = $this->translate('temp_file_missing');
  3172.                 }
  3173.             // if we haven't a temp file, and that we do check on uploads, we use is_uploaded_file()
  3174.             } else if (!$this->no_upload_check) {
  3175.                 if (!is_uploaded_file($this->file_src_pathname)) {
  3176.                     $this->processed = false;
  3177.                     $this->error = $this->translate('source_missing');
  3178.                 }
  3179.             // otherwise, if we don't check on uploaded files (local file for instance), we use file_exists()
  3180.             } else {
  3181.                 if (!file_exists($this->file_src_pathname)) {
  3182.                     $this->processed = false;
  3183.                     $this->error = $this->translate('source_missing');
  3184.                 }
  3185.             }
  3186.  
  3187.             // checks if the destination directory exists, and attempt to create it
  3188.             if (!$return_mode) {
  3189.                 if ($this->processed && !file_exists($this->file_dst_path)) {
  3190.                     if ($this->dir_auto_create) {
  3191.                         $this->log .= '- ' . $this->file_dst_path . ' doesn\'t exist. Attempting creation:';
  3192.                         if (!$this->rmkdir($this->file_dst_path, $this->dir_chmod)) {
  3193.                             $this->log .= ' failed<br />';
  3194.                             $this->processed = false;
  3195.                             $this->error = $this->translate('destination_dir');
  3196.                         } else {
  3197.                             $this->log .= ' success<br />';
  3198.                         }
  3199.                     } else {
  3200.                         $this->error = $this->translate('destination_dir_missing');
  3201.                     }
  3202.                 }
  3203.  
  3204.                 if ($this->processed && !is_dir($this->file_dst_path)) {
  3205.                     $this->processed = false;
  3206.                     $this->error = $this->translate('destination_path_not_dir');
  3207.                 }
  3208.  
  3209.                 // checks if the destination directory is writeable, and attempt to make it writeable
  3210.                 $hash = md5($this->file_dst_name_body . rand(1, 1000));
  3211.                 if ($this->processed && !($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) {
  3212.                     if ($this->dir_auto_chmod) {
  3213.                         $this->log .= '- ' . $this->file_dst_path . ' is not writeable. Attempting chmod:';
  3214.                         if (!@chmod($this->file_dst_path, $this->dir_chmod)) {
  3215.                             $this->log .= ' failed<br />';
  3216.                             $this->processed = false;
  3217.                             $this->error = $this->translate('destination_dir_write');
  3218.                         } else {
  3219.                             $this->log .= ' success<br />';
  3220.                             if (!($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) { // we re-check
  3221.                                 $this->processed = false;
  3222.                                 $this->error = $this->translate('destination_dir_write');
  3223.                             } else {
  3224.                                 @fclose($f);
  3225.                             }
  3226.                         }
  3227.                     } else {
  3228.                         $this->processed = false;
  3229.                         $this->error = $this->translate('destination_path_write');
  3230.                     }
  3231.                 } else {
  3232.                     if ($this->processed) @fclose($f);
  3233.                     @unlink($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''));
  3234.                 }
  3235.  
  3236.  
  3237.                 // if we have an uploaded file, and if it is the first process, and if we can't access the file directly (open_basedir restriction)
  3238.                 // then we create a temp file that will be used as the source file in subsequent processes
  3239.                 // the third condition is there to check if the file is not accessible *directly* (it already has positively gone through is_uploaded_file(), so it exists)
  3240.                 if (!$this->no_upload_check && empty($this->file_src_temp) && !@file_exists($this->file_src_pathname)) {
  3241.                     $this->log .= '- attempting to use a temp file:';
  3242.                     $hash = md5($this->file_dst_name_body . rand(1, 1000));
  3243.                     if (move_uploaded_file($this->file_src_pathname, $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''))) {
  3244.                         $this->file_src_pathname = $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
  3245.                         $this->file_src_temp = $this->file_src_pathname;
  3246.                         $this->log .= ' file created<br />';
  3247.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;temp file is: ' . $this->file_src_temp . '<br />';
  3248.                     } else {
  3249.                         $this->log .= ' failed<br />';
  3250.                         $this->processed = false;
  3251.                         $this->error = $this->translate('temp_file');
  3252.                     }
  3253.                 }
  3254.             }
  3255.         }
  3256.  
  3257.         if ($this->processed) {
  3258.  
  3259.             // check if we need to autorotate, to automatically pre-rotates the image according to EXIF data (JPEG only)
  3260.             $auto_flip = false;
  3261.             $auto_rotate = 0;
  3262.             if ($this->file_is_image && $this->image_auto_rotate && $this->image_src_type == 'jpg' && $this->function_enabled('exif_read_data')) {
  3263.                 $exif = @exif_read_data($this->file_src_pathname);
  3264.                 if (is_array($exif) && isset($exif['Orientation'])) {
  3265.                     $orientation = $exif['Orientation'];
  3266.                     switch($orientation) {
  3267.                       case 1:
  3268.                         $this->log .= '- EXIF orientation = 1 : default<br />';
  3269.                         break;
  3270.                       case 2:
  3271.                         $auto_flip = 'v';
  3272.                         $this->log .= '- EXIF orientation = 2 : vertical flip<br />';
  3273.                         break;
  3274.                       case 3:
  3275.                         $auto_rotate = 180;
  3276.                         $this->log .= '- EXIF orientation = 3 : 180 rotate left<br />';
  3277.                         break;
  3278.                       case 4:
  3279.                         $auto_flip = 'h';
  3280.                         $this->log .= '- EXIF orientation = 4 : horizontal flip<br />';
  3281.                         break;
  3282.                       case 5:
  3283.                         $auto_flip = 'h';
  3284.                         $auto_rotate = 90;
  3285.                         $this->log .= '- EXIF orientation = 5 : horizontal flip + 90 rotate right<br />';
  3286.                         break;
  3287.                       case 6:
  3288.                         $auto_rotate = 90;
  3289.                         $this->log .= '- EXIF orientation = 6 : 90 rotate right<br />';
  3290.                         break;
  3291.                       case 7:
  3292.                         $auto_flip = 'v';
  3293.                         $auto_rotate = 90;
  3294.                         $this->log .= '- EXIF orientation = 7 : vertical flip + 90 rotate right<br />';
  3295.                         break;
  3296.                       case 8:
  3297.                         $auto_rotate = 270;
  3298.                         $this->log .= '- EXIF orientation = 8 : 90 rotate left<br />';
  3299.                         break;
  3300.                       default:
  3301.                         $this->log .= '- EXIF orientation = '.$orientation.' : unknown<br />';
  3302.                         break;
  3303.                     }
  3304.                 } else {
  3305.                     $this->log .= '- EXIF data is invalid or missing<br />';
  3306.                 }
  3307.             } else {
  3308.                 if (!$this->image_auto_rotate) {
  3309.                     $this->log .= '- auto-rotate deactivated<br />';
  3310.                 } else if (!$this->image_src_type == 'jpg') {
  3311.                     $this->log .= '- auto-rotate applies only to JPEG images<br />';
  3312.                 } else if (!$this->function_enabled('exif_read_data')) {
  3313.                     $this->log .= '- auto-rotate requires function exif_read_data to be enabled<br />';
  3314.                 }
  3315.             }
  3316.  
  3317.             // do we do some image manipulation?
  3318.             $image_manipulation  = ($this->file_is_image && (
  3319.                                     $this->image_resize
  3320.                                  || $this->image_convert != ''
  3321.                                  || is_numeric($this->image_brightness)
  3322.                                  || is_numeric($this->image_contrast)
  3323.                                  || is_numeric($this->image_opacity)
  3324.                                  || is_numeric($this->image_threshold)
  3325.                                  || !empty($this->image_tint_color)
  3326.                                  || !empty($this->image_overlay_color)
  3327.                                  || $this->image_pixelate
  3328.                                  || $this->image_unsharp
  3329.                                  || !empty($this->image_text)
  3330.                                  || $this->image_greyscale
  3331.                                  || $this->image_negative
  3332.                                  || !empty($this->image_watermark)
  3333.                                  || $auto_rotate || $auto_flip
  3334.                                  || is_numeric($this->image_rotate)
  3335.                                  || is_numeric($this->jpeg_size)
  3336.                                  || !empty($this->image_flip)
  3337.                                  || !empty($this->image_crop)
  3338.                                  || !empty($this->image_precrop)
  3339.                                  || !empty($this->image_border)
  3340.                                  || !empty($this->image_border_transparent)
  3341.                                  || $this->image_frame > 0
  3342.                                  || $this->image_bevel > 0
  3343.                                  || $this->image_reflection_height));
  3344.  
  3345.             // we do a quick check to ensure the file is really an image
  3346.             // we can do this only now, as it would have failed before in case of open_basedir
  3347.             if ($image_manipulation && !@getimagesize($this->file_src_pathname)) {
  3348.                 $this->log .= '- the file is not an image!<br />';
  3349.                 $image_manipulation = false;
  3350.             }
  3351.  
  3352.             if ($image_manipulation) {
  3353.  
  3354.                 // make sure GD doesn't complain too much
  3355.                 @ini_set("gd.jpeg_ignore_warning", 1);
  3356.  
  3357.                 // checks if the source file is readable
  3358.                 if ($this->processed && !($f = @fopen($this->file_src_pathname, 'r'))) {
  3359.                     $this->processed = false;
  3360.                     $this->error = $this->translate('source_not_readable');
  3361.                 } else {
  3362.                     @fclose($f);
  3363.                 }
  3364.  
  3365.                 // we now do all the image manipulations
  3366.                 $this->log .= '- image resizing or conversion wanted<br />';
  3367.                 if ($this->gdversion()) {
  3368.                     switch($this->image_src_type) {
  3369.                         case 'jpg':
  3370.                             if (!$this->function_enabled('imagecreatefromjpeg')) {
  3371.                                 $this->processed = false;
  3372.                                 $this->error = $this->translate('no_create_support', array('JPEG'));
  3373.                             } else {
  3374.                                 $image_src = @imagecreatefromjpeg($this->file_src_pathname);
  3375.                                 if (!$image_src) {
  3376.                                     $this->processed = false;
  3377.                                     $this->error = $this->translate('create_error', array('JPEG'));
  3378.                                 } else {
  3379.                                     $this->log .= '- source image is JPEG<br />';
  3380.                                 }
  3381.                             }
  3382.                             break;
  3383.                         case 'png':
  3384.                             if (!$this->function_enabled('imagecreatefrompng')) {
  3385.                                 $this->processed = false;
  3386.                                 $this->error = $this->translate('no_create_support', array('PNG'));
  3387.                             } else {
  3388.                                 $image_src = @imagecreatefrompng($this->file_src_pathname);
  3389.                                 if (!$image_src) {
  3390.                                     $this->processed = false;
  3391.                                     $this->error = $this->translate('create_error', array('PNG'));
  3392.                                 } else {
  3393.                                     $this->log .= '- source image is PNG<br />';
  3394.                                 }
  3395.                             }
  3396.                             break;
  3397.                         case 'gif':
  3398.                             if (!$this->function_enabled('imagecreatefromgif')) {
  3399.                                 $this->processed = false;
  3400.                                 $this->error = $this->translate('no_create_support', array('GIF'));
  3401.                             } else {
  3402.                                 $image_src = @imagecreatefromgif($this->file_src_pathname);
  3403.                                 if (!$image_src) {
  3404.                                     $this->processed = false;
  3405.                                     $this->error = $this->translate('create_error', array('GIF'));
  3406.                                 } else {
  3407.                                     $this->log .= '- source image is GIF<br />';
  3408.                                 }
  3409.                             }
  3410.                             break;
  3411.                         case 'bmp':
  3412.                             if (!method_exists($this, 'imagecreatefrombmp')) {
  3413.                                 $this->processed = false;
  3414.                                 $this->error = $this->translate('no_create_support', array('BMP'));
  3415.                             } else {
  3416.                                 $image_src = @$this->imagecreatefrombmp($this->file_src_pathname);
  3417.                                 if (!$image_src) {
  3418.                                     $this->processed = false;
  3419.                                     $this->error = $this->translate('create_error', array('BMP'));
  3420.                                 } else {
  3421.                                     $this->log .= '- source image is BMP<br />';
  3422.                                 }
  3423.                             }
  3424.                             break;
  3425.                         default:
  3426.                             $this->processed = false;
  3427.                             $this->error = $this->translate('source_invalid');
  3428.                     }
  3429.                 } else {
  3430.                     $this->processed = false;
  3431.                     $this->error = $this->translate('gd_missing');
  3432.                 }
  3433.  
  3434.                 if ($this->processed && $image_src) {
  3435.  
  3436.                     // we have to set image_convert if it is not already
  3437.                     if (empty($this->image_convert)) {
  3438.                         $this->log .= '- setting destination file type to ' . $this->image_src_type . '<br />';
  3439.                         $this->image_convert = $this->image_src_type;
  3440.                     }
  3441.  
  3442.                     if (!in_array($this->image_convert, $this->image_supported)) {
  3443.                         $this->image_convert = 'jpg';
  3444.                     }
  3445.  
  3446.                     // we set the default color to be the background color if we don't output in a transparent format
  3447.                     if ($this->image_convert != 'png' && $this->image_convert != 'gif' && !empty($this->image_default_color) && empty($this->image_background_color)) $this->image_background_color = $this->image_default_color;
  3448.                     if (!empty($this->image_background_color)) $this->image_default_color = $this->image_background_color;
  3449.                     if (empty($this->image_default_color)) $this->image_default_color = '#FFFFFF';
  3450.  
  3451.                     $this->image_src_x = imagesx($image_src);
  3452.                     $this->image_src_y = imagesy($image_src);
  3453.                     $gd_version = $this->gdversion();
  3454.                     $ratio_crop = null;
  3455.  
  3456.                     if (!imageistruecolor($image_src)) {  // $this->image_src_type == 'gif'
  3457.                         $this->log .= '- image is detected as having a palette<br />';
  3458.                         $this->image_is_palette = true;
  3459.                         $this->image_transparent_color = imagecolortransparent($image_src);
  3460.                         if ($this->image_transparent_color >= 0 && imagecolorstotal($image_src) > $this->image_transparent_color) {
  3461.                             $this->image_is_transparent = true;
  3462.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;palette image is detected as transparent<br />';
  3463.                         }
  3464.                         // if the image has a palette (GIF), we convert it to true color, preserving transparency
  3465.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;convert palette image to true color<br />';
  3466.                         $true_color = imagecreatetruecolor($this->image_src_x, $this->image_src_y);
  3467.                         imagealphablending($true_color, false);
  3468.                         imagesavealpha($true_color, true);
  3469.                         for ($x = 0; $x < $this->image_src_x; $x++) {
  3470.                             for ($y = 0; $y < $this->image_src_y; $y++) {
  3471.                                 if ($this->image_transparent_color >= 0 && imagecolorat($image_src, $x, $y) == $this->image_transparent_color) {
  3472.                                     imagesetpixel($true_color, $x, $y, 127 << 24);
  3473.                                 } else {
  3474.                                     $rgb = imagecolorsforindex($image_src, imagecolorat($image_src, $x, $y));
  3475.                                     imagesetpixel($true_color, $x, $y, ($rgb['alpha'] << 24) | ($rgb['red'] << 16) | ($rgb['green'] << 8) | $rgb['blue']);
  3476.                                 }
  3477.                             }
  3478.                         }
  3479.                         $image_src = $this->imagetransfer($true_color, $image_src);
  3480.                         imagealphablending($image_src, false);
  3481.                         imagesavealpha($image_src, true);
  3482.                         $this->image_is_palette = false;
  3483.                     }
  3484.  
  3485.                     $image_dst = & $image_src;
  3486.  
  3487.                     // auto-flip image, according to EXIF data (JPEG only)
  3488.                     if ($gd_version >= 2 && !empty($auto_flip)) {
  3489.                         $this->log .= '- auto-flip image : ' . ($auto_flip == 'v' ? 'vertical' : 'horizontal') . '<br />';
  3490.                         $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
  3491.                         for ($x = 0; $x < $this->image_src_x; $x++) {
  3492.                             for ($y = 0; $y < $this->image_src_y; $y++){
  3493.                                 if (strpos($auto_flip, 'v') !== false) {
  3494.                                     imagecopy($tmp, $image_dst, $this->image_src_x - $x - 1, $y, $x, $y, 1, 1);
  3495.                                 } else {
  3496.                                     imagecopy($tmp, $image_dst, $x, $this->image_src_y - $y - 1, $x, $y, 1, 1);
  3497.                                 }
  3498.                             }
  3499.                         }
  3500.                         // we transfert tmp into image_dst
  3501.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  3502.                     }
  3503.  
  3504.                     // auto-rotate image, according to EXIF data (JPEG only)
  3505.                     if ($gd_version >= 2 && is_numeric($auto_rotate)) {
  3506.                         if (!in_array($auto_rotate, array(0, 90, 180, 270))) $auto_rotate = 0;
  3507.                         if ($auto_rotate != 0) {
  3508.                             if ($auto_rotate == 90 || $auto_rotate == 270) {
  3509.                                 $tmp = $this->imagecreatenew($this->image_src_y, $this->image_src_x);
  3510.                             } else {
  3511.                                 $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
  3512.                             }
  3513.                             $this->log .= '- auto-rotate image : ' . $auto_rotate . '<br />';
  3514.                             for ($x = 0; $x < $this->image_src_x; $x++) {
  3515.                                 for ($y = 0; $y < $this->image_src_y; $y++){
  3516.                                     if ($auto_rotate == 90) {
  3517.                                         imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_src_y - $y - 1, 1, 1);
  3518.                                     } else if ($auto_rotate == 180) {
  3519.                                         imagecopy($tmp, $image_dst, $x, $y, $this->image_src_x - $x - 1, $this->image_src_y - $y - 1, 1, 1);
  3520.                                     } else if ($auto_rotate == 270) {
  3521.                                         imagecopy($tmp, $image_dst, $y, $x, $this->image_src_x - $x - 1, $y, 1, 1);
  3522.                                     } else {
  3523.                                         imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1);
  3524.                                     }
  3525.                                 }
  3526.                             }
  3527.                             if ($auto_rotate == 90 || $auto_rotate == 270) {
  3528.                                 $t = $this->image_src_y;
  3529.                                 $this->image_src_y = $this->image_src_x;
  3530.                                 $this->image_src_x = $t;
  3531.                             }
  3532.                             // we transfert tmp into image_dst
  3533.                             $image_dst = $this->imagetransfer($tmp, $image_dst);
  3534.                         }
  3535.                     }
  3536.  
  3537.                     // pre-crop image, before resizing
  3538.                     if ((!empty($this->image_precrop))) {
  3539.                         list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_precrop, $this->image_src_x, $this->image_src_y, true, true);
  3540.                         $this->log .= '- pre-crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . ' <br />';
  3541.                         $this->image_src_x = $this->image_src_x - $cl - $cr;
  3542.                         $this->image_src_y = $this->image_src_y - $ct - $cb;
  3543.                         if ($this->image_src_x < 1) $this->image_src_x = 1;
  3544.                         if ($this->image_src_y < 1) $this->image_src_y = 1;
  3545.                         $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
  3546.  
  3547.                         // we copy the image into the recieving image
  3548.                         imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_src_x, $this->image_src_y);
  3549.  
  3550.                         // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent
  3551.                         if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) {
  3552.                             // use the background color if present
  3553.                             if (!empty($this->image_background_color)) {
  3554.                                 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
  3555.                                 $fill = imagecolorallocate($tmp, $red, $green, $blue);
  3556.                             } else {
  3557.                                 $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
  3558.                             }
  3559.                             // fills eventual negative margins
  3560.                             if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_src_x, -$ct, $fill);
  3561.                             if ($cr < 0) imagefilledrectangle($tmp, $this->image_src_x + $cr, 0, $this->image_src_x, $this->image_src_y, $fill);
  3562.                             if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_src_y + $cb, $this->image_src_x, $this->image_src_y, $fill);
  3563.                             if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl, $this->image_src_y, $fill);
  3564.                         }
  3565.  
  3566.                         // we transfert tmp into image_dst
  3567.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  3568.                     }
  3569.  
  3570.                     // resize image (and move image_src_x, image_src_y dimensions into image_dst_x, image_dst_y)
  3571.                     if ($this->image_resize) {
  3572.                         $this->log .= '- resizing...<br />';
  3573.                         $this->image_dst_x = $this->image_x;
  3574.                         $this->image_dst_y = $this->image_y;
  3575.  
  3576.                         // backward compatibility for soon to be deprecated settings
  3577.                         if ($this->image_ratio_no_zoom_in) {
  3578.                             $this->image_ratio = true;
  3579.                             $this->image_no_enlarging = true;
  3580.                         } else if ($this->image_ratio_no_zoom_out) {
  3581.                             $this->image_ratio = true;
  3582.                             $this->image_no_shrinking = true;
  3583.                         }
  3584.  
  3585.                         // keeps aspect ratio with x calculated from y
  3586.                         if ($this->image_ratio_x) {
  3587.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate x size<br />';
  3588.                             $this->image_dst_x = round(($this->image_src_x * $this->image_y) / $this->image_src_y);
  3589.                             $this->image_dst_y = $this->image_y;
  3590.  
  3591.                         // keeps aspect ratio with y calculated from x
  3592.                         } else if ($this->image_ratio_y) {
  3593.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate y size<br />';
  3594.                             $this->image_dst_x = $this->image_x;
  3595.                             $this->image_dst_y = round(($this->image_src_y * $this->image_x) / $this->image_src_x);
  3596.  
  3597.                         // keeps aspect ratio, calculating x and y so that the image is approx the set number of pixels
  3598.                         } else if (is_numeric($this->image_ratio_pixels)) {
  3599.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate x/y size to match a number of pixels<br />';
  3600.                             $pixels = $this->image_src_y * $this->image_src_x;
  3601.                             $diff = sqrt($this->image_ratio_pixels / $pixels);
  3602.                             $this->image_dst_x = round($this->image_src_x * $diff);
  3603.                             $this->image_dst_y = round($this->image_src_y * $diff);
  3604.  
  3605.                         // keeps aspect ratio with x and y dimensions, filling the space
  3606.                         } else if ($this->image_ratio_crop) {
  3607.                             if (!is_string($this->image_ratio_crop)) $this->image_ratio_crop = '';
  3608.                             $this->image_ratio_crop = strtolower($this->image_ratio_crop);
  3609.                             if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) {
  3610.                                 $this->image_dst_y = $this->image_y;
  3611.                                 $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
  3612.                                 $ratio_crop = array();
  3613.                                 $ratio_crop['x'] = $this->image_dst_x - $this->image_x;
  3614.                                 if (strpos($this->image_ratio_crop, 'l') !== false) {
  3615.                                     $ratio_crop['l'] = 0;
  3616.                                     $ratio_crop['r'] = $ratio_crop['x'];
  3617.                                 } else if (strpos($this->image_ratio_crop, 'r') !== false) {
  3618.                                     $ratio_crop['l'] = $ratio_crop['x'];
  3619.                                     $ratio_crop['r'] = 0;
  3620.                                 } else {
  3621.                                     $ratio_crop['l'] = round($ratio_crop['x']/2);
  3622.                                     $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l'];
  3623.                                 }
  3624.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_crop_x         : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')<br />';
  3625.                                 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
  3626.                             } else {
  3627.                                 $this->image_dst_x = $this->image_x;
  3628.                                 $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
  3629.                                 $ratio_crop = array();
  3630.                                 $ratio_crop['y'] = $this->image_dst_y - $this->image_y;
  3631.                                 if (strpos($this->image_ratio_crop, 't') !== false) {
  3632.                                     $ratio_crop['t'] = 0;
  3633.                                     $ratio_crop['b'] = $ratio_crop['y'];
  3634.                                 } else if (strpos($this->image_ratio_crop, 'b') !== false) {
  3635.                                     $ratio_crop['t'] = $ratio_crop['y'];
  3636.                                     $ratio_crop['b'] = 0;
  3637.                                 } else {
  3638.                                     $ratio_crop['t'] = round($ratio_crop['y']/2);
  3639.                                     $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t'];
  3640.                                 }
  3641.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_crop_y         : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')<br />';
  3642.                                 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
  3643.                             }
  3644.  
  3645.                         // keeps aspect ratio with x and y dimensions, fitting the image in the space, and coloring the rest
  3646.                         } else if ($this->image_ratio_fill) {
  3647.                             if (!is_string($this->image_ratio_fill)) $this->image_ratio_fill = '';
  3648.                             $this->image_ratio_fill = strtolower($this->image_ratio_fill);
  3649.                             if (($this->image_src_x/$this->image_x) < ($this->image_src_y/$this->image_y)) {
  3650.                                 $this->image_dst_y = $this->image_y;
  3651.                                 $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
  3652.                                 $ratio_crop = array();
  3653.                                 $ratio_crop['x'] = $this->image_dst_x - $this->image_x;
  3654.                                 if (strpos($this->image_ratio_fill, 'l') !== false) {
  3655.                                     $ratio_crop['l'] = 0;
  3656.                                     $ratio_crop['r'] = $ratio_crop['x'];
  3657.                                 } else if (strpos($this->image_ratio_fill, 'r') !== false) {
  3658.                                     $ratio_crop['l'] = $ratio_crop['x'];
  3659.                                     $ratio_crop['r'] = 0;
  3660.                                 } else {
  3661.                                     $ratio_crop['l'] = round($ratio_crop['x']/2);
  3662.                                     $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l'];
  3663.                                 }
  3664.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_fill_x         : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')<br />';
  3665.                                 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
  3666.                             } else {
  3667.                                 $this->image_dst_x = $this->image_x;
  3668.                                 $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
  3669.                                 $ratio_crop = array();
  3670.                                 $ratio_crop['y'] = $this->image_dst_y - $this->image_y;
  3671.                                 if (strpos($this->image_ratio_fill, 't') !== false) {
  3672.                                     $ratio_crop['t'] = 0;
  3673.                                     $ratio_crop['b'] = $ratio_crop['y'];
  3674.                                 } else if (strpos($this->image_ratio_fill, 'b') !== false) {
  3675.                                     $ratio_crop['t'] = $ratio_crop['y'];
  3676.                                     $ratio_crop['b'] = 0;
  3677.                                 } else {
  3678.                                     $ratio_crop['t'] = round($ratio_crop['y']/2);
  3679.                                     $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t'];
  3680.                                 }
  3681.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_fill_y         : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')<br />';
  3682.                                 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
  3683.                             }
  3684.  
  3685.                         // keeps aspect ratio with x and y dimensions
  3686.                         } else if ($this->image_ratio) {
  3687.                             if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) {
  3688.                                 $this->image_dst_x = $this->image_x;
  3689.                                 $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
  3690.                             } else {
  3691.                                 $this->image_dst_y = $this->image_y;
  3692.                                 $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
  3693.                             }
  3694.  
  3695.                         // resize to provided exact dimensions
  3696.                         } else {
  3697.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;use plain sizes<br />';
  3698.                             $this->image_dst_x = $this->image_x;
  3699.                             $this->image_dst_y = $this->image_y;
  3700.                         }
  3701.  
  3702.                         if ($this->image_dst_x < 1) $this->image_dst_x = 1;
  3703.                         if ($this->image_dst_y < 1) $this->image_dst_y = 1;
  3704.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_x y        : ' . $this->image_src_x . ' x ' . $this->image_src_y . '<br />';
  3705.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_dst_x y        : ' . $this->image_dst_x . ' x ' . $this->image_dst_y . '<br />';
  3706.  
  3707.                         // make sure we don't enlarge the image if we don't want to
  3708.                         if ($this->image_no_enlarging && ($this->image_src_x < $this->image_dst_x || $this->image_src_y < $this->image_dst_y)) {
  3709.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;cancel resizing, as it would enlarge the image!<br />';
  3710.                             $this->image_dst_x = $this->image_src_x;
  3711.                             $this->image_dst_y = $this->image_src_y;
  3712.                         }
  3713.  
  3714.                         // make sure we don't shrink the image if we don't want to
  3715.                         if ($this->image_no_shrinking && ($this->image_src_x > $this->image_dst_x || $this->image_src_y > $this->image_dst_y)) {
  3716.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;cancel resizing, as it would shrink the image!<br />';
  3717.                             $this->image_dst_x = $this->image_src_x;
  3718.                             $this->image_dst_y = $this->image_src_y;
  3719.                         }
  3720.  
  3721.                         // resize the image
  3722.                         if ($this->image_dst_x != $this->image_src_x && $this->image_dst_y != $this->image_src_y) {
  3723.                             $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  3724.  
  3725.                             if ($gd_version >= 2) {
  3726.                                 $res = imagecopyresampled($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y);
  3727.                             } else {
  3728.                                 $res = imagecopyresized($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y);
  3729.                             }
  3730.  
  3731.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;resized image object created<br />';
  3732.                              // we transfert tmp into image_dst
  3733.                             $image_dst = $this->imagetransfer($tmp, $image_dst);
  3734.                         }
  3735.  
  3736.                     } else {
  3737.                         $this->image_dst_x = $this->image_src_x;
  3738.                         $this->image_dst_y = $this->image_src_y;
  3739.                     }
  3740.  
  3741.                     // crop image (and also crops if image_ratio_crop is used)
  3742.                     if ((!empty($this->image_crop) || !is_null($ratio_crop))) {
  3743.                         list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_crop, $this->image_dst_x, $this->image_dst_y, true, true);
  3744.                         // we adjust the cropping if we use image_ratio_crop
  3745.                         if (!is_null($ratio_crop)) {
  3746.                             if (array_key_exists('t', $ratio_crop)) $ct += $ratio_crop['t'];
  3747.                             if (array_key_exists('r', $ratio_crop)) $cr += $ratio_crop['r'];
  3748.                             if (array_key_exists('b', $ratio_crop)) $cb += $ratio_crop['b'];
  3749.                             if (array_key_exists('l', $ratio_crop)) $cl += $ratio_crop['l'];
  3750.                         }
  3751.                         $this->log .= '- crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . ' <br />';
  3752.                         $this->image_dst_x = $this->image_dst_x - $cl - $cr;
  3753.                         $this->image_dst_y = $this->image_dst_y - $ct - $cb;
  3754.                         if ($this->image_dst_x < 1) $this->image_dst_x = 1;
  3755.                         if ($this->image_dst_y < 1) $this->image_dst_y = 1;
  3756.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  3757.  
  3758.                         // we copy the image into the recieving image
  3759.                         imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_dst_x, $this->image_dst_y);
  3760.  
  3761.                         // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent
  3762.                         if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) {
  3763.                             // use the background color if present
  3764.                             if (!empty($this->image_background_color)) {
  3765.                                 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
  3766.                                 $fill = imagecolorallocate($tmp, $red, $green, $blue);
  3767.                             } else {
  3768.                                 $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
  3769.                             }
  3770.                             // fills eventual negative margins
  3771.                             if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, -$ct-1, $fill);
  3772.                             if ($cr < 0) imagefilledrectangle($tmp, $this->image_dst_x + $cr, 0, $this->image_dst_x, $this->image_dst_y, $fill);
  3773.                             if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_dst_y + $cb, $this->image_dst_x, $this->image_dst_y, $fill);
  3774.                             if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl-1, $this->image_dst_y, $fill);
  3775.                         }
  3776.  
  3777.                         // we transfert tmp into image_dst
  3778.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  3779.                     }
  3780.  
  3781.                     // flip image
  3782.                     if ($gd_version >= 2 && !empty($this->image_flip)) {
  3783.                         $this->image_flip = strtolower($this->image_flip);
  3784.                         $this->log .= '- flip image : ' . $this->image_flip . '<br />';
  3785.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  3786.                         for ($x = 0; $x < $this->image_dst_x; $x++) {
  3787.                             for ($y = 0; $y < $this->image_dst_y; $y++){
  3788.                                 if (strpos($this->image_flip, 'v') !== false) {
  3789.                                     imagecopy($tmp, $image_dst, $this->image_dst_x - $x - 1, $y, $x, $y, 1, 1);
  3790.                                 } else {
  3791.                                     imagecopy($tmp, $image_dst, $x, $this->image_dst_y - $y - 1, $x, $y, 1, 1);
  3792.                                 }
  3793.                             }
  3794.                         }
  3795.                         // we transfert tmp into image_dst
  3796.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  3797.                     }
  3798.  
  3799.                     // rotate image
  3800.                     if ($gd_version >= 2 && is_numeric($this->image_rotate)) {
  3801.                         if (!in_array($this->image_rotate, array(0, 90, 180, 270))) $this->image_rotate = 0;
  3802.                         if ($this->image_rotate != 0) {
  3803.                             if ($this->image_rotate == 90 || $this->image_rotate == 270) {
  3804.                                 $tmp = $this->imagecreatenew($this->image_dst_y, $this->image_dst_x);
  3805.                             } else {
  3806.                                 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  3807.                             }
  3808.                             $this->log .= '- rotate image : ' . $this->image_rotate . '<br />';
  3809.                             for ($x = 0; $x < $this->image_dst_x; $x++) {
  3810.                                 for ($y = 0; $y < $this->image_dst_y; $y++){
  3811.                                     if ($this->image_rotate == 90) {
  3812.                                         imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_dst_y - $y - 1, 1, 1);
  3813.                                     } else if ($this->image_rotate == 180) {
  3814.                                         imagecopy($tmp, $image_dst, $x, $y, $this->image_dst_x - $x - 1, $this->image_dst_y - $y - 1, 1, 1);
  3815.                                     } else if ($this->image_rotate == 270) {
  3816.                                         imagecopy($tmp, $image_dst, $y, $x, $this->image_dst_x - $x - 1, $y, 1, 1);
  3817.                                     } else {
  3818.                                         imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1);
  3819.                                     }
  3820.                                 }
  3821.                             }
  3822.                             if ($this->image_rotate == 90 || $this->image_rotate == 270) {
  3823.                                 $t = $this->image_dst_y;
  3824.                                 $this->image_dst_y = $this->image_dst_x;
  3825.                                 $this->image_dst_x = $t;
  3826.                             }
  3827.                             // we transfert tmp into image_dst
  3828.                             $image_dst = $this->imagetransfer($tmp, $image_dst);
  3829.                         }
  3830.                     }
  3831.  
  3832.                     // pixelate image
  3833.                     if ((is_numeric($this->image_pixelate) && $this->image_pixelate > 0)) {
  3834.                         $this->log .= '- pixelate image (' . $this->image_pixelate . 'px)<br />';
  3835.                         $filter = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  3836.                         if ($gd_version >= 2) {
  3837.                             imagecopyresampled($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y);
  3838.                             imagecopyresampled($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate));
  3839.                         } else {
  3840.                             imagecopyresized($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y);
  3841.                             imagecopyresized($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate));
  3842.                         }
  3843.                         imagedestroy($filter);
  3844.                     }
  3845.  
  3846.                     // unsharp mask
  3847.                     if ($gd_version >= 2 && $this->image_unsharp && is_numeric($this->image_unsharp_amount) && is_numeric($this->image_unsharp_radius) && is_numeric($this->image_unsharp_threshold)) {
  3848.                         // Unsharp Mask for PHP - version 2.1.1
  3849.                         // Unsharp mask algorithm by Torstein Hønsi 2003-07.
  3850.                         // Used with permission
  3851.                         // Modified to support alpha transparency
  3852.                         if ($this->image_unsharp_amount > 500)    $this->image_unsharp_amount = 500;
  3853.                         $this->image_unsharp_amount = $this->image_unsharp_amount * 0.016;
  3854.                         if ($this->image_unsharp_radius > 50)    $this->image_unsharp_radius = 50;
  3855.                         $this->image_unsharp_radius = $this->image_unsharp_radius * 2;
  3856.                         if ($this->image_unsharp_threshold > 255)    $this->image_unsharp_threshold = 255;
  3857.                         $this->image_unsharp_radius = abs(round($this->image_unsharp_radius));
  3858.                         if ($this->image_unsharp_radius != 0) {
  3859.                             $this->image_dst_x = imagesx($image_dst); $this->image_dst_y = imagesy($image_dst);
  3860.                             $canvas = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true);
  3861.                             $blur = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true);
  3862.                             if ($this->function_enabled('imageconvolution')) { // PHP >= 5.1
  3863.                                 $matrix = array(array( 1, 2, 1 ), array( 2, 4, 2 ), array( 1, 2, 1 ));
  3864.                                 imagecopy($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
  3865.                                 imageconvolution($blur, $matrix, 16, 0);
  3866.                             } else {
  3867.                                 for ($i = 0; $i < $this->image_unsharp_radius; $i++) {
  3868.                                     imagecopy($blur, $image_dst, 0, 0, 1, 0, $this->image_dst_x - 1, $this->image_dst_y); // left
  3869.                                     $this->imagecopymergealpha($blur, $image_dst, 1, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // right
  3870.                                     $this->imagecopymergealpha($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // center
  3871.                                     imagecopy($canvas, $blur, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
  3872.                                     $this->imagecopymergealpha($blur, $canvas, 0, 0, 0, 1, $this->image_dst_x, $this->image_dst_y - 1, 33.33333 ); // up
  3873.                                     $this->imagecopymergealpha($blur, $canvas, 0, 1, 0, 0, $this->image_dst_x, $this->image_dst_y, 25); // down
  3874.                                 }
  3875.                             }
  3876.                             $p_new = array();
  3877.                             if($this->image_unsharp_threshold>0) {
  3878.                                 for ($x = 0; $x < $this->image_dst_x-1; $x++) {
  3879.                                     for ($y = 0; $y < $this->image_dst_y; $y++) {
  3880.                                         $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3881.                                         $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y));
  3882.                                         $p_new['red'] = (abs($p_orig['red'] - $p_blur['red']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'])) : $p_orig['red'];
  3883.                                         $p_new['green'] = (abs($p_orig['green'] - $p_blur['green']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'])) : $p_orig['green'];
  3884.                                         $p_new['blue'] = (abs($p_orig['blue'] - $p_blur['blue']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'])) : $p_orig['blue'];
  3885.                                         if (($p_orig['red'] != $p_new['red']) || ($p_orig['green'] != $p_new['green']) || ($p_orig['blue'] != $p_new['blue'])) {
  3886.                                             $color = imagecolorallocatealpha($image_dst, $p_new['red'], $p_new['green'], $p_new['blue'], $p_orig['alpha']);
  3887.                                             imagesetpixel($image_dst, $x, $y, $color);
  3888.                                         }
  3889.                                     }
  3890.                                 }
  3891.                             } else {
  3892.                                 for ($x = 0; $x < $this->image_dst_x; $x++) {
  3893.                                     for ($y = 0; $y < $this->image_dst_y; $y++) {
  3894.                                         $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3895.                                         $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y));
  3896.                                         $p_new['red'] = ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'];
  3897.                                         if ($p_new['red']>255) { $p_new['red']=255; } elseif ($p_new['red']<0) { $p_new['red']=0; }
  3898.                                         $p_new['green'] = ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'];
  3899.                                         if ($p_new['green']>255) { $p_new['green']=255; }  elseif ($p_new['green']<0) { $p_new['green']=0; }
  3900.                                         $p_new['blue'] = ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'];
  3901.                                         if ($p_new['blue']>255) { $p_new['blue']=255; } elseif ($p_new['blue']<0) { $p_new['blue']=0; }
  3902.                                         $color = imagecolorallocatealpha($image_dst, $p_new['red'], $p_new['green'], $p_new['blue'], $p_orig['alpha']);
  3903.                                         imagesetpixel($image_dst, $x, $y, $color);
  3904.                                     }
  3905.                                 }
  3906.                             }
  3907.                             imagedestroy($canvas);
  3908.                             imagedestroy($blur);
  3909.                         }
  3910.                     }
  3911.  
  3912.                     // add color overlay
  3913.                     if ($gd_version >= 2 && (is_numeric($this->image_overlay_opacity) && $this->image_overlay_opacity > 0 && !empty($this->image_overlay_color))) {
  3914.                         $this->log .= '- apply color overlay<br />';
  3915.                         list($red, $green, $blue) = $this->getcolors($this->image_overlay_color);
  3916.                         $filter = imagecreatetruecolor($this->image_dst_x, $this->image_dst_y);
  3917.                         $color = imagecolorallocate($filter, $red, $green, $blue);
  3918.                         imagefilledrectangle($filter, 0, 0, $this->image_dst_x, $this->image_dst_y, $color);
  3919.                         $this->imagecopymergealpha($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_overlay_opacity);
  3920.                         imagedestroy($filter);
  3921.                     }
  3922.  
  3923.                     // add brightness, contrast and tint, turns to greyscale and inverts colors
  3924.                     if ($gd_version >= 2 && ($this->image_negative || $this->image_greyscale || is_numeric($this->image_threshold)|| is_numeric($this->image_brightness) || is_numeric($this->image_contrast) || !empty($this->image_tint_color))) {
  3925.                         $this->log .= '- apply tint, light, contrast correction, negative, greyscale and threshold<br />';
  3926.                         if (!empty($this->image_tint_color)) list($tint_red, $tint_green, $tint_blue) = $this->getcolors($this->image_tint_color);
  3927.                         //imagealphablending($image_dst, true);
  3928.                         for($y=0; $y < $this->image_dst_y; $y++) {
  3929.                             for($x=0; $x < $this->image_dst_x; $x++) {
  3930.                                 if ($this->image_greyscale) {
  3931.                                     $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3932.                                     $r = $g = $b = round((0.2125 * $pixel['red']) + (0.7154 * $pixel['green']) + (0.0721 * $pixel['blue']));
  3933.                                     $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
  3934.                                     imagesetpixel($image_dst, $x, $y, $color);
  3935.                                     unset($color); unset($pixel);
  3936.                                 }
  3937.                                 if (is_numeric($this->image_threshold)) {
  3938.                                     $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3939.                                     $c = (round($pixel['red'] + $pixel['green'] + $pixel['blue']) / 3) - 127;
  3940.                                     $r = $g = $b = ($c > $this->image_threshold ? 255 : 0);
  3941.                                     $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
  3942.                                     imagesetpixel($image_dst, $x, $y, $color);
  3943.                                     unset($color); unset($pixel);
  3944.                                 }
  3945.                                 if (is_numeric($this->image_brightness)) {
  3946.                                     $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3947.                                     $r = max(min(round($pixel['red'] + (($this->image_brightness * 2))), 255), 0);
  3948.                                     $g = max(min(round($pixel['green'] + (($this->image_brightness * 2))), 255), 0);
  3949.                                     $b = max(min(round($pixel['blue'] + (($this->image_brightness * 2))), 255), 0);
  3950.                                     $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
  3951.                                     imagesetpixel($image_dst, $x, $y, $color);
  3952.                                     unset($color); unset($pixel);
  3953.                                 }
  3954.                                 if (is_numeric($this->image_contrast)) {
  3955.                                     $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3956.                                     $r = max(min(round(($this->image_contrast + 128) * $pixel['red'] / 128), 255), 0);
  3957.                                     $g = max(min(round(($this->image_contrast + 128) * $pixel['green'] / 128), 255), 0);
  3958.                                     $b = max(min(round(($this->image_contrast + 128) * $pixel['blue'] / 128), 255), 0);
  3959.                                     $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
  3960.                                     imagesetpixel($image_dst, $x, $y, $color);
  3961.                                     unset($color); unset($pixel);
  3962.                                 }
  3963.                                 if (!empty($this->image_tint_color)) {
  3964.                                     $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3965.                                     $r = min(round($tint_red * $pixel['red'] / 169), 255);
  3966.                                     $g = min(round($tint_green * $pixel['green'] / 169), 255);
  3967.                                     $b = min(round($tint_blue * $pixel['blue'] / 169), 255);
  3968.                                     $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
  3969.                                     imagesetpixel($image_dst, $x, $y, $color);
  3970.                                     unset($color); unset($pixel);
  3971.                                 }
  3972.                                 if (!empty($this->image_negative)) {
  3973.                                     $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  3974.                                     $r = round(255 - $pixel['red']);
  3975.                                     $g = round(255 - $pixel['green']);
  3976.                                     $b = round(255 - $pixel['blue']);
  3977.                                     $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']);
  3978.                                     imagesetpixel($image_dst, $x, $y, $color);
  3979.                                     unset($color); unset($pixel);
  3980.                                 }
  3981.                             }
  3982.                         }
  3983.                     }
  3984.  
  3985.                     // adds a border
  3986.                     if ($gd_version >= 2 && !empty($this->image_border)) {
  3987.                         list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border, $this->image_dst_x, $this->image_dst_y, true, false);
  3988.                         $this->log .= '- add border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '<br />';
  3989.                         $this->image_dst_x = $this->image_dst_x + $cl + $cr;
  3990.                         $this->image_dst_y = $this->image_dst_y + $ct + $cb;
  3991.                         if (!empty($this->image_border_color)) list($red, $green, $blue) = $this->getcolors($this->image_border_color);
  3992.                         $opacity = (is_numeric($this->image_border_opacity) ? (int) (127 - $this->image_border_opacity / 100 * 127): 0);
  3993.                         // we now create an image, that we fill with the border color
  3994.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  3995.                         $background = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity);
  3996.                         imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, $this->image_dst_y, $background);
  3997.                         // we then copy the source image into the new image, without merging so that only the border is actually kept
  3998.                         imagecopy($tmp, $image_dst, $cl, $ct, 0, 0, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct);
  3999.                         // we transfert tmp into image_dst
  4000.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  4001.                     }
  4002.  
  4003.                     // adds a fading-to-transparent border
  4004.                     if ($gd_version >= 2 && !empty($this->image_border_transparent)) {
  4005.                         list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border_transparent, $this->image_dst_x, $this->image_dst_y, true, false);
  4006.                         $this->log .= '- add transparent border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '<br />';
  4007.                         // we now create an image, that we fill with the border color
  4008.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  4009.                         // we then copy the source image into the new image, without the borders
  4010.                         imagecopy($tmp, $image_dst, $cl, $ct, $cl, $ct, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct);
  4011.                         // we now add the top border
  4012.                         $opacity = 100;
  4013.                         for ($y = $ct - 1; $y >= 0; $y--) {
  4014.                             $il = (int) ($ct > 0 ? ($cl * ($y / $ct)) : 0);
  4015.                             $ir = (int) ($ct > 0 ? ($cr * ($y / $ct)) : 0);
  4016.                             for ($x = $il; $x < $this->image_dst_x - $ir; $x++) {
  4017.                                 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4018.                                 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
  4019.                                 if ($alpha > 0) {
  4020.                                     if ($alpha > 1) $alpha = 1;
  4021.                                     $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'],  round((1 - $alpha) * 127));
  4022.                                     imagesetpixel($tmp, $x, $y, $color);
  4023.                                 }
  4024.                             }
  4025.                             if ($opacity > 0) $opacity = $opacity - (100 / $ct);
  4026.                         }
  4027.                         // we now add the right border
  4028.                         $opacity = 100;
  4029.                         for ($x = $this->image_dst_x - $cr; $x < $this->image_dst_x; $x++) {
  4030.                             $it = (int) ($cr > 0 ? ($ct * (($this->image_dst_x - $x - 1) / $cr)) : 0);
  4031.                             $ib = (int) ($cr > 0 ? ($cb * (($this->image_dst_x - $x - 1) / $cr)) : 0);
  4032.                             for ($y = $it; $y < $this->image_dst_y - $ib; $y++) {
  4033.                                 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4034.                                 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
  4035.                                 if ($alpha > 0) {
  4036.                                     if ($alpha > 1) $alpha = 1;
  4037.                                     $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'],  round((1 - $alpha) * 127));
  4038.                                     imagesetpixel($tmp, $x, $y, $color);
  4039.                                 }
  4040.                             }
  4041.                             if ($opacity > 0) $opacity = $opacity - (100 / $cr);
  4042.                         }
  4043.                         // we now add the bottom border
  4044.                         $opacity = 100;
  4045.                         for ($y = $this->image_dst_y - $cb; $y < $this->image_dst_y; $y++) {
  4046.                             $il = (int) ($cb > 0 ? ($cl * (($this->image_dst_y - $y - 1) / $cb)) : 0);
  4047.                             $ir = (int) ($cb > 0 ? ($cr * (($this->image_dst_y - $y - 1) / $cb)) : 0);
  4048.                             for ($x = $il; $x < $this->image_dst_x - $ir; $x++) {
  4049.                                 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4050.                                 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
  4051.                                 if ($alpha > 0) {
  4052.                                     if ($alpha > 1) $alpha = 1;
  4053.                                     $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'],  round((1 - $alpha) * 127));
  4054.                                     imagesetpixel($tmp, $x, $y, $color);
  4055.                                 }
  4056.                             }
  4057.                             if ($opacity > 0) $opacity = $opacity - (100 / $cb);
  4058.                         }
  4059.                         // we now add the left border
  4060.                         $opacity = 100;
  4061.                         for ($x = $cl - 1; $x >= 0; $x--) {
  4062.                             $it = (int) ($cl > 0 ? ($ct * ($x / $cl)) : 0);
  4063.                             $ib = (int) ($cl > 0 ? ($cb * ($x / $cl)) : 0);
  4064.                             for ($y = $it; $y < $this->image_dst_y - $ib; $y++) {
  4065.                                 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4066.                                 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
  4067.                                 if ($alpha > 0) {
  4068.                                     if ($alpha > 1) $alpha = 1;
  4069.                                     $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'],  round((1 - $alpha) * 127));
  4070.                                     imagesetpixel($tmp, $x, $y, $color);
  4071.                                 }
  4072.                             }
  4073.                             if ($opacity > 0) $opacity = $opacity - (100 / $cl);
  4074.                         }
  4075.                         // we transfert tmp into image_dst
  4076.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  4077.                     }
  4078.  
  4079.                     // add frame border
  4080.                     if ($gd_version >= 2 && is_numeric($this->image_frame)) {
  4081.                         if (is_array($this->image_frame_colors)) {
  4082.                             $vars = $this->image_frame_colors;
  4083.                             $this->log .= '- add frame : ' . implode(' ', $this->image_frame_colors) . '<br />';
  4084.                         } else {
  4085.                             $this->log .= '- add frame : ' . $this->image_frame_colors . '<br />';
  4086.                             $vars = explode(' ', $this->image_frame_colors);
  4087.                         }
  4088.                         $nb = sizeof($vars);
  4089.                         $this->image_dst_x = $this->image_dst_x + ($nb * 2);
  4090.                         $this->image_dst_y = $this->image_dst_y + ($nb * 2);
  4091.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  4092.                         imagecopy($tmp, $image_dst, $nb, $nb, 0, 0, $this->image_dst_x - ($nb * 2), $this->image_dst_y - ($nb * 2));
  4093.                         $opacity = (is_numeric($this->image_frame_opacity) ? (int) (127 - $this->image_frame_opacity / 100 * 127): 0);
  4094.                         for ($i=0; $i<$nb; $i++) {
  4095.                             list($red, $green, $blue) = $this->getcolors($vars[$i]);
  4096.                             $c = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity);
  4097.                             if ($this->image_frame == 1) {
  4098.                                 imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c);
  4099.                                 imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $this->image_dst_x - $i -1, $i, $c);
  4100.                                 imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c);
  4101.                                 imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c);
  4102.                             } else {
  4103.                                 imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c);
  4104.                                 imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $this->image_dst_x - $nb + $i, $nb - $i, $c);
  4105.                                 imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $nb - $i, $this->image_dst_y - $nb + $i, $c);
  4106.                                 imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c);
  4107.                             }
  4108.                         }
  4109.                         // we transfert tmp into image_dst
  4110.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  4111.                     }
  4112.  
  4113.                     // add bevel border
  4114.                     if ($gd_version >= 2 && $this->image_bevel > 0) {
  4115.                         if (empty($this->image_bevel_color1)) $this->image_bevel_color1 = '#FFFFFF';
  4116.                         if (empty($this->image_bevel_color2)) $this->image_bevel_color2 = '#000000';
  4117.                         list($red1, $green1, $blue1) = $this->getcolors($this->image_bevel_color1);
  4118.                         list($red2, $green2, $blue2) = $this->getcolors($this->image_bevel_color2);
  4119.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
  4120.                         imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
  4121.                         imagealphablending($tmp, true);
  4122.                         for ($i=0; $i<$this->image_bevel; $i++) {
  4123.                             $alpha = round(($i / $this->image_bevel) * 127);
  4124.                             $c1 = imagecolorallocatealpha($tmp, $red1, $green1, $blue1, $alpha);
  4125.                             $c2 = imagecolorallocatealpha($tmp, $red2, $green2, $blue2, $alpha);
  4126.                             imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c1);
  4127.                             imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i, $this->image_dst_x - $i -1, $i, $c2);
  4128.                             imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c2);
  4129.                             imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c1);
  4130.                         }
  4131.                         // we transfert tmp into image_dst
  4132.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  4133.                     }
  4134.  
  4135.                     // add watermark image
  4136.                     if ($this->image_watermark!='' && file_exists($this->image_watermark)) {
  4137.                         $this->log .= '- add watermark<br />';
  4138.                         $this->image_watermark_position = strtolower($this->image_watermark_position);
  4139.                         $watermark_info = getimagesize($this->image_watermark);
  4140.                         $watermark_type = (array_key_exists(2, $watermark_info) ? $watermark_info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG
  4141.                         $watermark_checked = false;
  4142.                         if ($watermark_type == IMAGETYPE_GIF) {
  4143.                             if (!$this->function_enabled('imagecreatefromgif')) {
  4144.                                 $this->error = $this->translate('watermark_no_create_support', array('GIF'));
  4145.                             } else {
  4146.                                 $filter = @imagecreatefromgif($this->image_watermark);
  4147.                                 if (!$filter) {
  4148.                                     $this->error = $this->translate('watermark_create_error', array('GIF'));
  4149.                                 } else {
  4150.                                     $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is GIF<br />';
  4151.                                     $watermark_checked = true;
  4152.                                 }
  4153.                             }
  4154.                         } else if ($watermark_type == IMAGETYPE_JPEG) {
  4155.                             if (!$this->function_enabled('imagecreatefromjpeg')) {
  4156.                                 $this->error = $this->translate('watermark_no_create_support', array('JPEG'));
  4157.                             } else {
  4158.                                 $filter = @imagecreatefromjpeg($this->image_watermark);
  4159.                                 if (!$filter) {
  4160.                                     $this->error = $this->translate('watermark_create_error', array('JPEG'));
  4161.                                 } else {
  4162.                                     $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is JPEG<br />';
  4163.                                     $watermark_checked = true;
  4164.                                 }
  4165.                             }
  4166.                         } else if ($watermark_type == IMAGETYPE_PNG) {
  4167.                             if (!$this->function_enabled('imagecreatefrompng')) {
  4168.                                 $this->error = $this->translate('watermark_no_create_support', array('PNG'));
  4169.                             } else {
  4170.                                 $filter = @imagecreatefrompng($this->image_watermark);
  4171.                                 if (!$filter) {
  4172.                                     $this->error = $this->translate('watermark_create_error', array('PNG'));
  4173.                                 } else {
  4174.                                     $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is PNG<br />';
  4175.                                     $watermark_checked = true;
  4176.                                 }
  4177.                             }
  4178.                         } else if ($watermark_type == IMAGETYPE_BMP) {
  4179.                             if (!method_exists($this, 'imagecreatefrombmp')) {
  4180.                                 $this->error = $this->translate('watermark_no_create_support', array('BMP'));
  4181.                             } else {
  4182.                                 $filter = @$this->imagecreatefrombmp($this->image_watermark);
  4183.                                 if (!$filter) {
  4184.                                     $this->error = $this->translate('watermark_create_error', array('BMP'));
  4185.                                 } else {
  4186.                                     $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is BMP<br />';
  4187.                                     $watermark_checked = true;
  4188.                                 }
  4189.                             }
  4190.                         } else {
  4191.                             $this->error = $this->translate('watermark_invalid');
  4192.                         }
  4193.                         if ($watermark_checked) {
  4194.                             $watermark_dst_width  = $watermark_src_width  = imagesx($filter);
  4195.                             $watermark_dst_height = $watermark_src_height = imagesy($filter);
  4196.  
  4197.                             // if watermark is too large/tall, resize it first
  4198.                             if ((!$this->image_watermark_no_zoom_out && ($watermark_dst_width > $this->image_dst_x || $watermark_dst_height > $this->image_dst_y))
  4199.                              || (!$this->image_watermark_no_zoom_in && $watermark_dst_width < $this->image_dst_x && $watermark_dst_height < $this->image_dst_y)) {
  4200.                                 $canvas_width  = $this->image_dst_x - abs($this->image_watermark_x);
  4201.                                 $canvas_height = $this->image_dst_y - abs($this->image_watermark_y);
  4202.                                 if (($watermark_src_width/$canvas_width) > ($watermark_src_height/$canvas_height)) {
  4203.                                     $watermark_dst_width = $canvas_width;
  4204.                                     $watermark_dst_height = intval($watermark_src_height*($canvas_width / $watermark_src_width));
  4205.                                 } else {
  4206.                                     $watermark_dst_height = $canvas_height;
  4207.                                     $watermark_dst_width = intval($watermark_src_width*($canvas_height / $watermark_src_height));
  4208.                                 }
  4209.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark resized from '.$watermark_src_width.'x'.$watermark_src_height.' to '.$watermark_dst_width.'x'.$watermark_dst_height.'<br />';
  4210.  
  4211.                             }
  4212.                             // determine watermark position
  4213.                             $watermark_x = 0;
  4214.                             $watermark_y = 0;
  4215.                             if (is_numeric($this->image_watermark_x)) {
  4216.                                 if ($this->image_watermark_x < 0) {
  4217.                                     $watermark_x = $this->image_dst_x - $watermark_dst_width + $this->image_watermark_x;
  4218.                                 } else {
  4219.                                     $watermark_x = $this->image_watermark_x;
  4220.                                 }
  4221.                             } else {
  4222.                                 if (strpos($this->image_watermark_position, 'r') !== false) {
  4223.                                     $watermark_x = $this->image_dst_x - $watermark_dst_width;
  4224.                                 } else if (strpos($this->image_watermark_position, 'l') !== false) {
  4225.                                     $watermark_x = 0;
  4226.                                 } else {
  4227.                                     $watermark_x = ($this->image_dst_x - $watermark_dst_width) / 2;
  4228.                                 }
  4229.                             }
  4230.                             if (is_numeric($this->image_watermark_y)) {
  4231.                                 if ($this->image_watermark_y < 0) {
  4232.                                     $watermark_y = $this->image_dst_y - $watermark_dst_height + $this->image_watermark_y;
  4233.                                 } else {
  4234.                                     $watermark_y = $this->image_watermark_y;
  4235.                                 }
  4236.                             } else {
  4237.                                 if (strpos($this->image_watermark_position, 'b') !== false) {
  4238.                                     $watermark_y = $this->image_dst_y - $watermark_dst_height;
  4239.                                 } else if (strpos($this->image_watermark_position, 't') !== false) {
  4240.                                     $watermark_y = 0;
  4241.                                 } else {
  4242.                                     $watermark_y = ($this->image_dst_y - $watermark_dst_height) / 2;
  4243.                                 }
  4244.                             }
  4245.                             imagealphablending($image_dst, true);
  4246.                             imagecopyresampled($image_dst, $filter, $watermark_x, $watermark_y, 0, 0, $watermark_dst_width, $watermark_dst_height, $watermark_src_width, $watermark_src_height);
  4247.                         } else {
  4248.                             $this->error = $this->translate('watermark_invalid');
  4249.                         }
  4250.                     }
  4251.  
  4252.                     // add text
  4253.                     if (!empty($this->image_text)) {
  4254.                         $this->log .= '- add text<br />';
  4255.  
  4256.                         // calculate sizes in human readable format
  4257.                         $src_size       = $this->file_src_size / 1024;
  4258.                         $src_size_mb    = number_format($src_size / 1024, 1, ".", " ");
  4259.                         $src_size_kb    = number_format($src_size, 1, ".", " ");
  4260.                         $src_size_human = ($src_size > 1024 ? $src_size_mb . " MB" : $src_size_kb . " kb");
  4261.  
  4262.                         $this->image_text = str_replace(
  4263.                             array('[src_name]',
  4264.                                   '[src_name_body]',
  4265.                                   '[src_name_ext]',
  4266.                                   '[src_pathname]',
  4267.                                   '[src_mime]',
  4268.                                   '[src_size]',
  4269.                                   '[src_size_kb]',
  4270.                                   '[src_size_mb]',
  4271.                                   '[src_size_human]',
  4272.                                   '[src_x]',
  4273.                                   '[src_y]',
  4274.                                   '[src_pixels]',
  4275.                                   '[src_type]',
  4276.                                   '[src_bits]',
  4277.                                   '[dst_path]',
  4278.                                   '[dst_name_body]',
  4279.                                   '[dst_name_ext]',
  4280.                                   '[dst_name]',
  4281.                                   '[dst_pathname]',
  4282.                                   '[dst_x]',
  4283.                                   '[dst_y]',
  4284.                                   '[date]',
  4285.                                   '[time]',
  4286.                                   '[host]',
  4287.                                   '[server]',
  4288.                                   '[ip]',
  4289.                                   '[gd_version]'),
  4290.                             array($this->file_src_name,
  4291.                                   $this->file_src_name_body,
  4292.                                   $this->file_src_name_ext,
  4293.                                   $this->file_src_pathname,
  4294.                                   $this->file_src_mime,
  4295.                                   $this->file_src_size,
  4296.                                   $src_size_kb,
  4297.                                   $src_size_mb,
  4298.                                   $src_size_human,
  4299.                                   $this->image_src_x,
  4300.                                   $this->image_src_y,
  4301.                                   $this->image_src_pixels,
  4302.                                   $this->image_src_type,
  4303.                                   $this->image_src_bits,
  4304.                                   $this->file_dst_path,
  4305.                                   $this->file_dst_name_body,
  4306.                                   $this->file_dst_name_ext,
  4307.                                   $this->file_dst_name,
  4308.                                   $this->file_dst_pathname,
  4309.                                   $this->image_dst_x,
  4310.                                   $this->image_dst_y,
  4311.                                   date('Y-m-d'),
  4312.                                   date('H:i:s'),
  4313.                                   (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'n/a'),
  4314.                                   (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'n/a'),
  4315.                                   (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'n/a'),
  4316.                                   $this->gdversion(true)),
  4317.                             $this->image_text);
  4318.  
  4319.                         if (!is_numeric($this->image_text_padding)) $this->image_text_padding = 0;
  4320.                         if (!is_numeric($this->image_text_line_spacing)) $this->image_text_line_spacing = 0;
  4321.                         if (!is_numeric($this->image_text_padding_x)) $this->image_text_padding_x = $this->image_text_padding;
  4322.                         if (!is_numeric($this->image_text_padding_y)) $this->image_text_padding_y = $this->image_text_padding;
  4323.                         $this->image_text_position = strtolower($this->image_text_position);
  4324.                         $this->image_text_direction = strtolower($this->image_text_direction);
  4325.                         $this->image_text_alignment = strtolower($this->image_text_alignment);
  4326.  
  4327.                         $font_type = 'gd';
  4328.  
  4329.                         // if the font is a string with a GDF font path, we assume that we might want to load a font
  4330.                         if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.gdf') {
  4331.                             if (strpos($this->image_text_font, '/') === false) $this->image_text_font = "./" . $this->image_text_font;
  4332.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;try to load font ' . $this->image_text_font . '... ';
  4333.                             if ($this->image_text_font = @imageloadfont($this->image_text_font)) {
  4334.                                 $this->log .=  'success<br />';
  4335.                             } else {
  4336.                                 $this->log .=  'error<br />';
  4337.                                 $this->image_text_font = 5;
  4338.                             }
  4339.                         }
  4340.  
  4341.                         // if the font is a string with a TTF font path, we check if we can access the font file
  4342.                         if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.ttf') {
  4343.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;try to load font ' . $this->image_text_font . '... ';
  4344.                             if (strpos($this->image_text_font, '/') === false) $this->image_text_font = "./" . $this->image_text_font;
  4345.                             if (file_exists($this->image_text_font) && is_readable($this->image_text_font)) {
  4346.                                 $this->log .=  'success<br />';
  4347.                                 $font_type = 'tt';
  4348.                             } else {
  4349.                                 $this->log .=  'error<br />';
  4350.                                 $this->image_text_font = 5;
  4351.                             }
  4352.                         }
  4353.  
  4354.                         // get the text bounding box (GD fonts)
  4355.                         if ($font_type == 'gd') {
  4356.                             $text = explode("\n", $this->image_text);
  4357.                             $char_width = imagefontwidth($this->image_text_font);
  4358.                             $char_height = imagefontheight($this->image_text_font);
  4359.                             $text_height = 0;
  4360.                             $text_width = 0;
  4361.                             $line_height = 0;
  4362.                             $line_width = 0;
  4363.                             foreach ($text as $k => $v) {
  4364.                                 if ($this->image_text_direction == 'v') {
  4365.                                     $h = ($char_width * strlen($v));
  4366.                                     if ($h > $text_height) $text_height = $h;
  4367.                                     $line_width = $char_height;
  4368.                                     $text_width += $line_width + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0);
  4369.                                 } else {
  4370.                                     $w = ($char_width * strlen($v));
  4371.                                     if ($w > $text_width) $text_width = $w;
  4372.                                     $line_height = $char_height;
  4373.                                     $text_height += $line_height + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0);
  4374.                                 }
  4375.                             }
  4376.                             $text_width  += (2 * $this->image_text_padding_x);
  4377.                             $text_height += (2 * $this->image_text_padding_y);
  4378.  
  4379.                         // get the text bounding box (TrueType fonts)
  4380.                         } else if ($font_type == 'tt') {
  4381.                             $text = $this->image_text;
  4382.                             if (!$this->image_text_angle) $this->image_text_angle = $this->image_text_direction == 'v' ? 90 : 0;
  4383.                             $text_height = 0;
  4384.                             $text_width = 0;
  4385.                             $text_offset_x = 0;
  4386.                             $text_offset_y = 0;
  4387.                             $rect = imagettfbbox($this->image_text_size, $this->image_text_angle, $this->image_text_font, $text );
  4388.                             if ($rect) {
  4389.                                 $minX = min(array($rect[0],$rect[2],$rect[4],$rect[6]));
  4390.                                 $maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6]));
  4391.                                 $minY = min(array($rect[1],$rect[3],$rect[5],$rect[7]));
  4392.                                 $maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7]));
  4393.                                 $text_offset_x = abs($minX) - 1;
  4394.                                 $text_offset_y = abs($minY) - 1;
  4395.                                 $text_width = $maxX - $minX + (2 * $this->image_text_padding_x);
  4396.                                 $text_height = $maxY - $minY + (2 * $this->image_text_padding_y);
  4397.                             }
  4398.                         }
  4399.  
  4400.                         // position the text block
  4401.                         $text_x = 0;
  4402.                         $text_y = 0;
  4403.                         if (is_numeric($this->image_text_x)) {
  4404.                             if ($this->image_text_x < 0) {
  4405.                                 $text_x = $this->image_dst_x - $text_width + $this->image_text_x;
  4406.                             } else {
  4407.                                 $text_x = $this->image_text_x;
  4408.                             }
  4409.                         } else {
  4410.                             if (strpos($this->image_text_position, 'r') !== false) {
  4411.                                 $text_x = $this->image_dst_x - $text_width;
  4412.                             } else if (strpos($this->image_text_position, 'l') !== false) {
  4413.                                 $text_x = 0;
  4414.                             } else {
  4415.                                 $text_x = ($this->image_dst_x - $text_width) / 2;
  4416.                             }
  4417.                         }
  4418.                         if (is_numeric($this->image_text_y)) {
  4419.                             if ($this->image_text_y < 0) {
  4420.                                 $text_y = $this->image_dst_y - $text_height + $this->image_text_y;
  4421.                             } else {
  4422.                                 $text_y = $this->image_text_y;
  4423.                             }
  4424.                         } else {
  4425.                             if (strpos($this->image_text_position, 'b') !== false) {
  4426.                                 $text_y = $this->image_dst_y - $text_height;
  4427.                             } else if (strpos($this->image_text_position, 't') !== false) {
  4428.                                 $text_y = 0;
  4429.                             } else {
  4430.                                 $text_y = ($this->image_dst_y - $text_height) / 2;
  4431.                             }
  4432.                         }
  4433.  
  4434.                         // add a background, maybe transparent
  4435.                         if (!empty($this->image_text_background)) {
  4436.                             list($red, $green, $blue) = $this->getcolors($this->image_text_background);
  4437.                             if ($gd_version >= 2 && (is_numeric($this->image_text_background_opacity)) && $this->image_text_background_opacity >= 0 && $this->image_text_background_opacity <= 100) {
  4438.                                 $filter = imagecreatetruecolor($text_width, $text_height);
  4439.                                 $background_color = imagecolorallocate($filter, $red, $green, $blue);
  4440.                                 imagefilledrectangle($filter, 0, 0, $text_width, $text_height, $background_color);
  4441.                                 $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $text_width, $text_height, $this->image_text_background_opacity);
  4442.                                 imagedestroy($filter);
  4443.                             } else {
  4444.                                 $background_color = imagecolorallocate($image_dst ,$red, $green, $blue);
  4445.                                 imagefilledrectangle($image_dst, $text_x, $text_y, $text_x + $text_width, $text_y + $text_height, $background_color);
  4446.                             }
  4447.                         }
  4448.  
  4449.                         $text_x += $this->image_text_padding_x;
  4450.                         $text_y += $this->image_text_padding_y;
  4451.                         $t_width = $text_width - (2 * $this->image_text_padding_x);
  4452.                         $t_height = $text_height - (2 * $this->image_text_padding_y);
  4453.                         list($red, $green, $blue) = $this->getcolors($this->image_text_color);
  4454.  
  4455.                         // add the text, maybe transparent
  4456.                         if ($gd_version >= 2 && (is_numeric($this->image_text_opacity)) && $this->image_text_opacity >= 0 && $this->image_text_opacity <= 100) {
  4457.                             if ($t_width < 0) $t_width = 0;
  4458.                             if ($t_height < 0) $t_height = 0;
  4459.                             $filter = $this->imagecreatenew($t_width, $t_height, false, true);
  4460.                             $text_color = imagecolorallocate($filter ,$red, $green, $blue);
  4461.  
  4462.                             if ($font_type == 'gd') {
  4463.                                 foreach ($text as $k => $v) {
  4464.                                     if ($this->image_text_direction == 'v') {
  4465.                                         imagestringup($filter,
  4466.                                                       $this->image_text_font,
  4467.                                                       $k * ($line_width  + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
  4468.                                                       $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))) ,
  4469.                                                       $v,
  4470.                                                       $text_color);
  4471.                                     } else {
  4472.                                         imagestring($filter,
  4473.                                                     $this->image_text_font,
  4474.                                                     ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
  4475.                                                     $k * ($line_height  + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
  4476.                                                     $v,
  4477.                                                     $text_color);
  4478.                                     }
  4479.                                 }
  4480.                             } else if ($font_type == 'tt') {
  4481.                                 imagettftext($filter,
  4482.                                              $this->image_text_size,
  4483.                                              $this->image_text_angle,
  4484.                                              $text_offset_x,
  4485.                                              $text_offset_y,
  4486.                                              $text_color,
  4487.                                              $this->image_text_font,
  4488.                                              $text);
  4489.                             }
  4490.                             $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $t_width, $t_height, $this->image_text_opacity);
  4491.                             imagedestroy($filter);
  4492.  
  4493.                         } else {
  4494.                             $text_color = imagecolorallocate($image_dst ,$red, $green, $blue);
  4495.                             if ($font_type == 'gd') {
  4496.                                 foreach ($text as $k => $v) {
  4497.                                     if ($this->image_text_direction == 'v') {
  4498.                                         imagestringup($image_dst,
  4499.                                                       $this->image_text_font,
  4500.                                                       $text_x + $k * ($line_width  + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
  4501.                                                       $text_y + $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
  4502.                                                       $v,
  4503.                                                       $text_color);
  4504.                                     } else {
  4505.                                         imagestring($image_dst,
  4506.                                                     $this->image_text_font,
  4507.                                                     $text_x + ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
  4508.                                                     $text_y + $k * ($line_height  + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
  4509.                                                     $v,
  4510.                                                     $text_color);
  4511.                                     }
  4512.                                 }
  4513.                             } else if ($font_type == 'tt') {
  4514.                                 imagettftext($image_dst,
  4515.                                              $this->image_text_size,
  4516.                                              $this->image_text_angle,
  4517.                                              $text_offset_x + ($this->image_dst_x / 2) - ($text_width / 2) + $this->image_text_padding_x,
  4518.                                              $text_offset_y + ($this->image_dst_y / 2) - ($text_height / 2) + $this->image_text_padding_y,
  4519.                                              $text_color,
  4520.                                              $this->image_text_font,
  4521.                                              $text);
  4522.                             }
  4523.                         }
  4524.                     }
  4525.  
  4526.                     // add a reflection
  4527.                     if ($this->image_reflection_height) {
  4528.                         $this->log .= '- add reflection : ' . $this->image_reflection_height . '<br />';
  4529.                         // we decode image_reflection_height, which can be a integer, a string in pixels or percentage
  4530.                         $image_reflection_height = $this->image_reflection_height;
  4531.                         if (strpos($image_reflection_height, '%')>0) $image_reflection_height = $this->image_dst_y * (str_replace('%','',$image_reflection_height / 100));
  4532.                         if (strpos($image_reflection_height, 'px')>0) $image_reflection_height = str_replace('px','',$image_reflection_height);
  4533.                         $image_reflection_height = (int) $image_reflection_height;
  4534.                         if ($image_reflection_height > $this->image_dst_y) $image_reflection_height = $this->image_dst_y;
  4535.                         if (empty($this->image_reflection_opacity)) $this->image_reflection_opacity = 60;
  4536.                         // create the new destination image
  4537.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y + $image_reflection_height + $this->image_reflection_space, true);
  4538.                         $transparency = $this->image_reflection_opacity;
  4539.  
  4540.                         // copy the original image
  4541.                         imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0));
  4542.  
  4543.                         // we have to make sure the extra bit is the right color, or transparent
  4544.                         if ($image_reflection_height + $this->image_reflection_space > 0) {
  4545.                             // use the background color if present
  4546.                             if (!empty($this->image_background_color)) {
  4547.                                 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
  4548.                                 $fill = imagecolorallocate($tmp, $red, $green, $blue);
  4549.                             } else {
  4550.                                 $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
  4551.                             }
  4552.                             // fill in from the edge of the extra bit
  4553.                             imagefill($tmp, round($this->image_dst_x / 2), $this->image_dst_y + $image_reflection_height + $this->image_reflection_space - 1, $fill);
  4554.                         }
  4555.  
  4556.                         // copy the reflection
  4557.                         for ($y = 0; $y < $image_reflection_height; $y++) {
  4558.                             for ($x = 0; $x < $this->image_dst_x; $x++) {
  4559.                                 $pixel_b = imagecolorsforindex($tmp, imagecolorat($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space));
  4560.                                 $pixel_o = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $this->image_dst_y - $y - 1 + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0)));
  4561.                                 $alpha_o = 1 - ($pixel_o['alpha'] / 127);
  4562.                                 $alpha_b = 1 - ($pixel_b['alpha'] / 127);
  4563.                                 $opacity = $alpha_o * $transparency / 100;
  4564.                                 if ($opacity > 0) {
  4565.                                     $red   = round((($pixel_o['red']   * $opacity) + ($pixel_b['red']  ) * $alpha_b) / ($alpha_b + $opacity));
  4566.                                     $green = round((($pixel_o['green'] * $opacity) + ($pixel_b['green']) * $alpha_b) / ($alpha_b + $opacity));
  4567.                                     $blue  = round((($pixel_o['blue']  * $opacity) + ($pixel_b['blue'] ) * $alpha_b) / ($alpha_b + $opacity));
  4568.                                     $alpha = ($opacity + $alpha_b);
  4569.                                     if ($alpha > 1) $alpha = 1;
  4570.                                     $alpha =  round((1 - $alpha) * 127);
  4571.                                     $color = imagecolorallocatealpha($tmp, $red, $green, $blue, $alpha);
  4572.                                     imagesetpixel($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space, $color);
  4573.                                 }
  4574.                             }
  4575.                             if ($transparency > 0) $transparency = $transparency - ($this->image_reflection_opacity / $image_reflection_height);
  4576.                         }
  4577.  
  4578.                         // copy the resulting image into the destination image
  4579.                         $this->image_dst_y = $this->image_dst_y + $image_reflection_height + $this->image_reflection_space;
  4580.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  4581.                     }
  4582.  
  4583.                     // change opacity
  4584.                     if ($gd_version >= 2 && is_numeric($this->image_opacity) && $this->image_opacity < 100) {
  4585.                         $this->log .= '- change opacity<br />';
  4586.                         // create the new destination image
  4587.                         $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, true);
  4588.                         for($y=0; $y < $this->image_dst_y; $y++) {
  4589.                             for($x=0; $x < $this->image_dst_x; $x++) {
  4590.                                 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4591.                                 $alpha = $pixel['alpha'] + round((127 - $pixel['alpha']) * (100 - $this->image_opacity) / 100);
  4592.                                 if ($alpha > 127) $alpha = 127;
  4593.                                 if ($alpha > 0) {
  4594.                                     $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], $alpha);
  4595.                                     imagesetpixel($tmp, $x, $y, $color);
  4596.                                 }
  4597.                             }
  4598.                         }
  4599.                         // copy the resulting image into the destination image
  4600.                         $image_dst = $this->imagetransfer($tmp, $image_dst);
  4601.                     }
  4602.  
  4603.                     // reduce the JPEG image to a set desired size
  4604.                     if (is_numeric($this->jpeg_size) && $this->jpeg_size > 0 && ($this->image_convert == 'jpeg' || $this->image_convert == 'jpg')) {
  4605.                         // inspired by: JPEGReducer class version 1, 25 November 2004, Author: Huda M ElMatsani, justhuda at netscape dot net
  4606.                         $this->log .= '- JPEG desired file size : ' . $this->jpeg_size . '<br />';
  4607.                         // calculate size of each image. 75%, 50%, and 25% quality
  4608.                         ob_start(); imagejpeg($image_dst,null,75);  $buffer = ob_get_contents(); ob_end_clean();
  4609.                         $size75 = strlen($buffer);
  4610.                         ob_start(); imagejpeg($image_dst,null,50);  $buffer = ob_get_contents(); ob_end_clean();
  4611.                         $size50 = strlen($buffer);
  4612.                         ob_start(); imagejpeg($image_dst,null,25);  $buffer = ob_get_contents(); ob_end_clean();
  4613.                         $size25 = strlen($buffer);
  4614.  
  4615.                         // make sure we won't divide by 0
  4616.                         if ($size50 == $size25) $size50++;
  4617.                         if ($size75 == $size50 || $size75 == $size25) $size75++;
  4618.  
  4619.                         // calculate gradient of size reduction by quality
  4620.                         $mgrad1 = 25 / ($size50-$size25);
  4621.                         $mgrad2 = 25 / ($size75-$size50);
  4622.                         $mgrad3 = 50 / ($size75-$size25);
  4623.                         $mgrad  = ($mgrad1 + $mgrad2 + $mgrad3) / 3;
  4624.                         // result of approx. quality factor for expected size
  4625.                         $q_factor = round($mgrad * ($this->jpeg_size - $size50) + 50);
  4626.  
  4627.                         if ($q_factor<1) {
  4628.                             $this->jpeg_quality=1;
  4629.                         } elseif ($q_factor>100) {
  4630.                             $this->jpeg_quality=100;
  4631.                         } else {
  4632.                             $this->jpeg_quality=$q_factor;
  4633.                         }
  4634.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;JPEG quality factor set to ' . $this->jpeg_quality . '<br />';
  4635.                     }
  4636.  
  4637.                     // converts image from true color, and fix transparency if needed
  4638.                     $this->log .= '- converting...<br />';
  4639.                     $this->image_dst_type = $this->image_convert;
  4640.                     switch($this->image_convert) {
  4641.                         case 'gif':
  4642.                             // if the image is true color, we convert it to a palette
  4643.                             if (imageistruecolor($image_dst)) {
  4644.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;true color to palette<br />';
  4645.                                 // creates a black and white mask
  4646.                                 $mask = array(array());
  4647.                                 for ($x = 0; $x < $this->image_dst_x; $x++) {
  4648.                                     for ($y = 0; $y < $this->image_dst_y; $y++) {
  4649.                                         $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4650.                                         $mask[$x][$y] = $pixel['alpha'];
  4651.                                     }
  4652.                                 }
  4653.                                 list($red, $green, $blue) = $this->getcolors($this->image_default_color);
  4654.                                 // first, we merge the image with the background color, so we know which colors we will have
  4655.                                 for ($x = 0; $x < $this->image_dst_x; $x++) {
  4656.                                     for ($y = 0; $y < $this->image_dst_y; $y++) {
  4657.                                         if ($mask[$x][$y] > 0){
  4658.                                             // we have some transparency. we combine the color with the default color
  4659.                                             $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4660.                                             $alpha = ($mask[$x][$y] / 127);
  4661.                                             $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha)));
  4662.                                             $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha)));
  4663.                                             $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha)));
  4664.                                             $color = imagecolorallocate($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']);
  4665.                                             imagesetpixel($image_dst, $x, $y, $color);
  4666.                                         }
  4667.                                     }
  4668.                                 }
  4669.                                 // transforms the true color image into palette, with its merged default color
  4670.                                 if (empty($this->image_background_color)) {
  4671.                                     imagetruecolortopalette($image_dst, true, 255);
  4672.                                     $transparency = imagecolorallocate($image_dst, 254, 1, 253);
  4673.                                     imagecolortransparent($image_dst, $transparency);
  4674.                                     // make the transparent areas transparent
  4675.                                     for ($x = 0; $x < $this->image_dst_x; $x++) {
  4676.                                         for ($y = 0; $y < $this->image_dst_y; $y++) {
  4677.                                             // we test wether we have enough opacity to justify keeping the color
  4678.                                             if ($mask[$x][$y] > 120) imagesetpixel($image_dst, $x, $y, $transparency);
  4679.                                         }
  4680.                                     }
  4681.                                 }
  4682.                                 unset($mask);
  4683.                             }
  4684.                             break;
  4685.                         case 'jpg':
  4686.                         case 'bmp':
  4687.                             // if the image doesn't support any transparency, then we merge it with the default color
  4688.                             $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;fills in transparency with default color<br />';
  4689.                             list($red, $green, $blue) = $this->getcolors($this->image_default_color);
  4690.                             $transparency = imagecolorallocate($image_dst, $red, $green, $blue);
  4691.                             // make the transaparent areas transparent
  4692.                             for ($x = 0; $x < $this->image_dst_x; $x++) {
  4693.                                 for ($y = 0; $y < $this->image_dst_y; $y++) {
  4694.                                     // we test wether we have some transparency, in which case we will merge the colors
  4695.                                     if (imageistruecolor($image_dst)) {
  4696.                                         $rgba = imagecolorat($image_dst, $x, $y);
  4697.                                         $pixel = array('red' => ($rgba >> 16) & 0xFF,
  4698.                                                        'green' => ($rgba >> 8) & 0xFF,
  4699.                                                        'blue' => $rgba & 0xFF,
  4700.                                                        'alpha' => ($rgba & 0x7F000000) >> 24);
  4701.                                     } else {
  4702.                                         $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
  4703.                                     }
  4704.                                     if ($pixel['alpha'] == 127) {
  4705.                                         // we have full transparency. we make the pixel transparent
  4706.                                         imagesetpixel($image_dst, $x, $y, $transparency);
  4707.                                     } else if ($pixel['alpha'] > 0) {
  4708.                                         // we have some transparency. we combine the color with the default color
  4709.                                         $alpha = ($pixel['alpha'] / 127);
  4710.                                         $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha)));
  4711.                                         $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha)));
  4712.                                         $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha)));
  4713.                                         $color = imagecolorclosest($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']);
  4714.                                         imagesetpixel($image_dst, $x, $y, $color);
  4715.                                     }
  4716.                                 }
  4717.                             }
  4718.  
  4719.                             break;
  4720.                         default:
  4721.                             break;
  4722.                     }
  4723.  
  4724.                     // interlace options
  4725.                     if($this->image_interlace) imageinterlace($image_dst, true);
  4726.  
  4727.                     // outputs image
  4728.                     $this->log .= '- saving image...<br />';
  4729.                     switch($this->image_convert) {
  4730.                         case 'jpeg':
  4731.                         case 'jpg':
  4732.                             if (!$return_mode) {
  4733.                                 $result = @imagejpeg($image_dst, $this->file_dst_pathname, $this->jpeg_quality);
  4734.                             } else {
  4735.                                 ob_start();
  4736.                                 $result = @imagejpeg($image_dst, null, $this->jpeg_quality);
  4737.                                 $return_content = ob_get_contents();
  4738.                                 ob_end_clean();
  4739.                             }
  4740.                             if (!$result) {
  4741.                                 $this->processed = false;
  4742.                                 $this->error = $this->translate('file_create', array('JPEG'));
  4743.                             } else {
  4744.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;JPEG image created<br />';
  4745.                             }
  4746.                             break;
  4747.                         case 'png':
  4748.                             imagealphablending( $image_dst, false );
  4749.                             imagesavealpha( $image_dst, true );
  4750.                             if (!$return_mode) {
  4751.                                 if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) {
  4752.                                     $result = @imagepng($image_dst, $this->file_dst_pathname, $this->png_compression);
  4753.                                 } else {
  4754.                                     $result = @imagepng($image_dst, $this->file_dst_pathname);
  4755.                                 }
  4756.                             } else {
  4757.                                 ob_start();
  4758.                                 if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) {
  4759.                                     $result = @imagepng($image_dst, null, $this->png_compression);
  4760.                                 } else {
  4761.                                     $result = @imagepng($image_dst);
  4762.                                 }
  4763.                                 $return_content = ob_get_contents();
  4764.                                 ob_end_clean();
  4765.                             }
  4766.                             if (!$result) {
  4767.                                 $this->processed = false;
  4768.                                 $this->error = $this->translate('file_create', array('PNG'));
  4769.                             } else {
  4770.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;PNG image created<br />';
  4771.                             }
  4772.                             break;
  4773.                         case 'gif':
  4774.                             if (!$return_mode) {
  4775.                                 $result = @imagegif($image_dst, $this->file_dst_pathname);
  4776.                             } else {
  4777.                                 ob_start();
  4778.                                 $result = @imagegif($image_dst);
  4779.                                 $return_content = ob_get_contents();
  4780.                                 ob_end_clean();
  4781.                             }
  4782.                             if (!$result) {
  4783.                                 $this->processed = false;
  4784.                                 $this->error = $this->translate('file_create', array('GIF'));
  4785.                             } else {
  4786.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;GIF image created<br />';
  4787.                             }
  4788.                             break;
  4789.                         case 'bmp':
  4790.                             if (!$return_mode) {
  4791.                                 $result = $this->imagebmp($image_dst, $this->file_dst_pathname);
  4792.                             } else {
  4793.                                 ob_start();
  4794.                                 $result = $this->imagebmp($image_dst);
  4795.                                 $return_content = ob_get_contents();
  4796.                                 ob_end_clean();
  4797.                             }
  4798.                             if (!$result) {
  4799.                                 $this->processed = false;
  4800.                                 $this->error = $this->translate('file_create', array('BMP'));
  4801.                             } else {
  4802.                                 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;BMP image created<br />';
  4803.                             }
  4804.                             break;
  4805.  
  4806.                         default:
  4807.                             $this->processed = false;
  4808.                             $this->error = $this->translate('no_conversion_type');
  4809.                     }
  4810.                     if ($this->processed) {
  4811.                         if (is_resource($image_src)) imagedestroy($image_src);
  4812.                         if (is_resource($image_dst)) imagedestroy($image_dst);
  4813.                         $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image objects destroyed<br />';
  4814.                     }
  4815.                 }
  4816.  
  4817.             } else {
  4818.                 $this->log .= '- no image processing wanted<br />';
  4819.  
  4820.                 if (!$return_mode) {
  4821.                     // copy the file to its final destination. we don't use move_uploaded_file here
  4822.                     // if we happen to have open_basedir restrictions, it is a temp file that we copy, not the original uploaded file
  4823.                     if (!copy($this->file_src_pathname, $this->file_dst_pathname)) {
  4824.                         $this->processed = false;
  4825.                         $this->error = $this->translate('copy_failed');
  4826.                     }
  4827.                 } else {
  4828.                     // returns the file, so that its content can be received by the caller
  4829.                     $return_content = @file_get_contents($this->file_src_pathname);
  4830.                     if ($return_content === FALSE) {
  4831.                         $this->processed = false;
  4832.                         $this->error = $this->translate('reading_failed');
  4833.                     }
  4834.                 }
  4835.             }
  4836.         }
  4837.  
  4838.         if ($this->processed) {
  4839.             $this->log .= '- <b>process OK</b><br />';
  4840.         } else {
  4841.             $this->log .= '- <b>error</b>: ' . $this->error . '<br />';
  4842.         }
  4843.  
  4844.         // we reinit all the vars
  4845.         $this->init();
  4846.  
  4847.         // we may return the image content
  4848.         if ($return_mode) return $return_content;
  4849.  
  4850.     }
  4851.  
  4852.     /**
  4853.      * Deletes the uploaded file from its temporary location
  4854.      *
  4855.      * When PHP uploads a file, it stores it in a temporary location.
  4856.      * When you {@link process} the file, you actually copy the resulting file to the given location, it doesn't alter the original file.
  4857.      * Once you have processed the file as many times as you wanted, you can delete the uploaded file.
  4858.      * If there is open_basedir restrictions, the uploaded file is in fact a temporary file
  4859.      *
  4860.      * You might want not to use this function if you work on local files, as it will delete the source file
  4861.      *
  4862.      * @access public
  4863.      */
  4864.     function clean() {
  4865.         $this->log .= '<b>cleanup</b><br />';
  4866.         $this->log .= '- delete temp file '  . $this->file_src_pathname . '<br />';
  4867.         @unlink($this->file_src_pathname);
  4868.     }
  4869.  
  4870.  
  4871.     /**
  4872.      * Opens a BMP image
  4873.      *
  4874.      * This function has been written by DHKold, and is used with permission of the author
  4875.      *
  4876.      * @access public
  4877.      */
  4878.     function imagecreatefrombmp($filename) {
  4879.         if (! $f1 = fopen($filename,"rb")) return false;
  4880.  
  4881.         $file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
  4882.         if ($file['file_type'] != 19778) return false;
  4883.  
  4884.         $bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
  4885.                       '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
  4886.                       '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
  4887.         $bmp['colors'] = pow(2,$bmp['bits_per_pixel']);
  4888.         if ($bmp['size_bitmap'] == 0) $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
  4889.         $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel']/8;
  4890.         $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
  4891.         $bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel']/4);
  4892.         $bmp['decal'] -= floor($bmp['width']*$bmp['bytes_per_pixel']/4);
  4893.         $bmp['decal'] = 4-(4*$bmp['decal']);
  4894.         if ($bmp['decal'] == 4) $bmp['decal'] = 0;
  4895.  
  4896.         $palette = array();
  4897.         if ($bmp['colors'] < 16777216) {
  4898.             $palette = unpack('V'.$bmp['colors'], fread($f1,$bmp['colors']*4));
  4899.         }
  4900.  
  4901.         $im = fread($f1,$bmp['size_bitmap']);
  4902.         $vide = chr(0);
  4903.  
  4904.         $res = imagecreatetruecolor($bmp['width'],$bmp['height']);
  4905.         $P = 0;
  4906.         $Y = $bmp['height']-1;
  4907.         while ($Y >= 0) {
  4908.             $X=0;
  4909.             while ($X < $bmp['width']) {
  4910.                 if ($bmp['bits_per_pixel'] == 24)
  4911.                     $color = unpack("V",substr($im,$P,3).$vide);
  4912.                 elseif ($bmp['bits_per_pixel'] == 16) {
  4913.                     $color = unpack("n",substr($im,$P,2));
  4914.                     $color[1] = $palette[$color[1]+1];
  4915.                 } elseif ($bmp['bits_per_pixel'] == 8) {
  4916.                     $color = unpack("n",$vide.substr($im,$P,1));
  4917.                     $color[1] = $palette[$color[1]+1];
  4918.                 } elseif ($bmp['bits_per_pixel'] == 4) {
  4919.                     $color = unpack("n",$vide.substr($im,floor($P),1));
  4920.                     if (($P*2)%2 == 0) $color[1] = ($color[1] >> 4) ; else $color[1] = ($color[1] & 0x0F);
  4921.                     $color[1] = $palette[$color[1]+1];
  4922.                 } elseif ($bmp['bits_per_pixel'] == 1)  {
  4923.                     $color = unpack("n",$vide.substr($im,floor($P),1));
  4924.                     if     (($P*8)%8 == 0) $color[1] =  $color[1]        >>7;
  4925.                     elseif (($P*8)%8 == 1) $color[1] = ($color[1] & 0x40)>>6;
  4926.                     elseif (($P*8)%8 == 2) $color[1] = ($color[1] & 0x20)>>5;
  4927.                     elseif (($P*8)%8 == 3) $color[1] = ($color[1] & 0x10)>>4;
  4928.                     elseif (($P*8)%8 == 4) $color[1] = ($color[1] & 0x8)>>3;
  4929.                     elseif (($P*8)%8 == 5) $color[1] = ($color[1] & 0x4)>>2;
  4930.                     elseif (($P*8)%8 == 6) $color[1] = ($color[1] & 0x2)>>1;
  4931.                     elseif (($P*8)%8 == 7) $color[1] = ($color[1] & 0x1);
  4932.                     $color[1] = $palette[$color[1]+1];
  4933.                 } else
  4934.                     return FALSE;
  4935.                 imagesetpixel($res,$X,$Y,$color[1]);
  4936.                 $X++;
  4937.                 $P += $bmp['bytes_per_pixel'];
  4938.             }
  4939.             $Y--;
  4940.             $P+=$bmp['decal'];
  4941.         }
  4942.         fclose($f1);
  4943.         return $res;
  4944.     }
  4945.  
  4946.     /**
  4947.      * Saves a BMP image
  4948.      *
  4949.      * This function has been published on the PHP website, and can be used freely
  4950.      *
  4951.      * @access public
  4952.      */
  4953.     function imagebmp(&$im, $filename = "") {
  4954.  
  4955.         if (!$im) return false;
  4956.         $w = imagesx($im);
  4957.         $h = imagesy($im);
  4958.         $result = '';
  4959.  
  4960.         // if the image is not true color, we convert it first
  4961.         if (!imageistruecolor($im)) {
  4962.             $tmp = imagecreatetruecolor($w, $h);
  4963.             imagecopy($tmp, $im, 0, 0, 0, 0, $w, $h);
  4964.             imagedestroy($im);
  4965.             $im = & $tmp;
  4966.         }
  4967.  
  4968.         $biBPLine = $w * 3;
  4969.         $biStride = ($biBPLine + 3) & ~3;
  4970.         $biSizeImage = $biStride * $h;
  4971.         $bfOffBits = 54;
  4972.         $bfSize = $bfOffBits + $biSizeImage;
  4973.  
  4974.         $result .= substr('BM', 0, 2);
  4975.         $result .=  pack ('VvvV', $bfSize, 0, 0, $bfOffBits);
  4976.         $result .= pack ('VVVvvVVVVVV', 40, $w, $h, 1, 24, 0, $biSizeImage, 0, 0, 0, 0);
  4977.  
  4978.         $numpad = $biStride - $biBPLine;
  4979.         for ($y = $h - 1; $y >= 0; --$y) {
  4980.             for ($x = 0; $x < $w; ++$x) {
  4981.                 $col = imagecolorat ($im, $x, $y);
  4982.                 $result .=  substr(pack ('V', $col), 0, 3);
  4983.             }
  4984.             for ($i = 0; $i < $numpad; ++$i)
  4985.                 $result .= pack ('C', 0);
  4986.         }
  4987.  
  4988.         if($filename==""){
  4989.             echo $result;
  4990.         } else {
  4991.             $file = fopen($filename, "wb");
  4992.             fwrite($file, $result);
  4993.             fclose($file);
  4994.         }
  4995.         return true;
  4996.     }
  4997. }
  4998. ?>
Add Comment
Please, Sign In to add comment