diff --git a/Distribucion.php b/Distribucion.php index fb50160..80822b6 100644 --- a/Distribucion.php +++ b/Distribucion.php @@ -70,7 +70,7 @@ class Distribucion { // if(strstr($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip')) { // // introducimos la cabecera que indica que el contenido está comprimido // header('Content-Encoding: gzip'); -// // y comprime al m�ximo la información antes de enviarla +// // y comprime al máximo la información antes de enviarla // return gzencode($pagina, 9); // } return $pagina; // enviamos sin comprimir diff --git a/Imagen.php b/Imagen.php new file mode 100644 index 0000000..50cf725 --- /dev/null +++ b/Imagen.php @@ -0,0 +1,179 @@ +. + * + */ +//Para comprimir las imágenes +require_once('Zebra_Image.php'); +define("HAYQUEGRABAR", 1); +define("HAYQUEBORRAR", 2); +define("NOHACERNADA", 3); + +class Imagen { + private $archivoSubido; + public $archivoComprimido; + private $extension; + private $dirData; + + public function __construct($directorio = "img.data") + { + $this->dirData = $directorio; + } + + public function determinaAccion($campo) + { + if (isset($_POST[$campo]) && $_POST[$campo] == "") { + return HAYQUEBORRAR; //Hay que borrar el archivo de imagen + } elseif ($_FILES[$campo]['error'] == 0) { + return HAYQUEGUARDAR; //Hay que guardar el archivo de imagen enviado + } else { + return NOHACERNADA; //No hay que hacer nada + } + } + + public function procesaEnvio($campo, &$mensaje) + { + try { + // Undefined | Multiple Files | $_FILES Corruption Attack + // If this request falls under any of them, treat it invalid. + if ( + !isset($_FILES[$campo]['error']) || + is_array($_FILES[$campo]['error']) + ) { + throw new RuntimeException('Parámetros inválidos.'); + } + + // Check $_FILES['upfile']['error'] value. + switch ($_FILES[$campo]['error']) { + case UPLOAD_ERR_OK: + break; + case UPLOAD_ERR_NO_FILE: + throw new RuntimeException('No se ha enviado ningún fichero.'); + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + throw new RuntimeException('Se ha excedido el tamaño máximo.'); + default: + throw new RuntimeException('Error desconocido.'); + } + + // DO NOT TRUST $_FILES['upfile']['mime'] VALUE !! + // Check MIME Type by yourself. + $finfo = new finfo(FILEINFO_MIME_TYPE); + if (false === $ext = array_search( + $finfo->file($_FILES[$campo]['tmp_name']), + array( + 'jpg' => 'image/jpeg', + 'png' => 'image/png', + 'gif' => 'image/gif', + ), + true + )) { + throw new RuntimeException('Formato de imagen inválido, no es {jpg, png, gif}'); + } + $this->extension = $ext; + // You should name it uniquely. + // DO NOT USE $_FILES['upfile']['name'] WITHOUT ANY VALIDATION !! + // On this example, obtain safe unique name from its binary data. + $this->archivoSubido = sprintf('tmp/%s.%s', sha1_file($_FILES[$campo]['tmp_name']), $ext); + if (!move_uploaded_file($_FILES[$campo]['tmp_name'], $this->archivoSubido)) { + throw new RuntimeException('Fallo moviendo el archivo subido.'); + } + //Todo ha ido correcto + return true; + } catch (RuntimeException $e) { + $mensaje = $e->getMessage(); + return false; + } + } + + public function mueveImagenId($id, &$mensaje) + { + if (!$this->comprimeArchivo($id, $mensaje)) { + return false; + } else { + return true; + } + } + + private function generaNombre() + { + //De momento no se utiliza + $i = 0; + $salir = false; + $nombre = strftime("%Y%m%d%H%M%S"); + //limita a 1000 intentos el buscar un archivo inexistente + while ($i++<1000 and !$salir) { + $test = $nombre . $i; + $fichero = $this->dirData . "/" . $test . "." . $this->extension; + if (!file_exists($fichero)) { + $salir = true; + } + } + if (!salir) { + throw new Exception("No se ha podido encontrar un nombre de archivo único en ".$this->dirData, 1); + } + return $fichero; + } + + private function comprimeArchivo($id, &$mensaje) + { + $zebra = new Zebra_Image(); + $zebra->source_path = $this->archivoSubido; + $this->archivoComprimido = $id . "." . $this->extension; + $zebra->target_path = $this->archivoComprimido; + $zebra->jpeg_quality = 100; + + // some additional properties that can be set + // read about them in the documentation + $zebra->preserve_aspect_ratio = true; + $zebra->enlarge_smaller_images = true; + $zebra->preserve_time = true; + + // resize the image to exactly 100x100 pixels by using the "crop from center" method + // (read more in the overview section or in the documentation) + // and if there is an error, check what the error is about + if (!$zebra->resize(640, 480, ZEBRA_IMAGE_CROP_CENTER)) { + // if there was an error, let's see what the error is about + switch ($zebra->error) { + case 1: $mensaje = 'El fichero origen no se ha encontrado!'; + break; + case 2: $mensaje = 'No se puede leer el archivo origen ' . $this->archivoSubido; + break; + case 3: $mensaje = 'No se pudo escribir el archivo destino ' . $this->archivoComprimido; + break; + case 4: $mensaje = 'Formato de fichero origen no soportado ' . $this->archivoSubido; + break; + case 5: $mensaje = 'Formato de fichero destino no soportado ' . $this->archivoComprimido; + break; + case 6: $mensaje = 'La versión de la biblioteca GD no soporta el formato de destino ' . $this->archivoComprimido; + break; + case 7: $mensaje = 'La biblioteca GD no está instalada'; + break; + case 8: $mensaje = 'el comando "chmod" está deshabilitado por configuración'; + break; + } + return false; + } else { + // + //unlink($this->archivoSubido); + return true; + } + } +} + +?> diff --git a/Mantenimiento.php b/Mantenimiento.php index 998dd32..e72bd57 100644 --- a/Mantenimiento.php +++ b/Mantenimiento.php @@ -207,7 +207,7 @@ class Mantenimiento { $valor = '' . $valor; } if (strstr($this->campos[$clave]['Comment'], "imagen") && isset($valor)) { - $msj = ''; + $msj = ''; $msj .= $this->creaModal($valor, $id); $valor = $msj; } @@ -312,6 +312,7 @@ class Mantenimiento { $comando = "insert into " . $this->tabla . " ("; $lista = explode("&", $_POST['listacampos']); $primero = true; + $hayImagen = false; //Añade la lista de campos foreach ($lista as $campo) { if ($campo == "") { @@ -344,7 +345,22 @@ class Mantenimiento { } $valor = $_POST[$campo] == "on" ? '1' : $valor; } else { - $valor = $_POST[$campo] == "" ? "null" : '"' . $_POST[$campo] . '"'; + if (stristr("imagen", $this->campos[$campo]['Type'])) { + //procesa el envío de la imagen + $imagen = new Imagen(); + $accion = $imagen->determinaAccion($campo); + if ($accion != NOHACERNADA) { + // El código 3 es no hacer nada. + $mensaje = ""; + if (!$imagen->procesaEnvio("insertar", $campo, $mensaje)) { + return $this->panelMensaje($mensaje, "danger", "ERROR PROCESANDO IMAGEN"); + } + $hayImgen = true; + } + + } else { + $valor = $_POST[$campo] == "" ? "null" : '"' . $_POST[$campo] . '"'; + } } $comando.="$coma " . $valor; } @@ -352,13 +368,58 @@ class Mantenimiento { if (!$this->bdd->ejecuta($comando)) { return $this->errorBD($comando); } + $id = $this->bdd->ultimoId(); + if ($hayImagen) { + //Tiene que recuperar el id del registro insertado y actualizar el archivo de imagen + if (!$imagen->mueveImagenId($id, $mensaje)) { + return $this->panelMensaje($mensaje, "danger", "ERROR COMPRIMIENDO IMAGEN"); + } + $comando = "update " . $this->tabla . " set " . $campo . "='" . $imagen->archivoComprimido . "' where id='" . $id ."';"; + if (!$this->bdd->ejecuta($comando)) { + return $this->errorBD($comando); + } + } $this->datosURL['opc'] = 'inicial'; $this->datosURL['id'] = null; $cabecera = "refresh:".PAUSA.";url=".$this->montaURL(); header($cabecera); - return $this->panelMensaje("Se ha insertado el registro con la clave " . $this->bdd->ultimoId(), "info", "Información"); + return $this->panelMensaje("Se ha insertado el registro con la clave " . $id, "info", "Información"); //return "

montaURL()."\">Se ha insertado el registro con la clave " . $this->bdd->ultimoId() . "

"; } + + private function procesaEnvioImagen($operacion, $campo) + { + + switch ($operacion) { + /* + * Insertar: + * Ha incluido archivo? sino fin + * Si se ha incluido ¿se ha subido correctamente? sino error + * mover archivo a tmp con un nombre + * comprimir con un nombre genérico y único en la carpeta de datos + * devolver el nombre del archivo creado como valor a guardar en el campo imagen + * (se podría activar una vez insertado el registro que se renombrara el archivo con el id del elemento y se cambiara el campo) + */ + + + /* + * Borrar: + * Hay imagen asociada? sino fin + * Se borra el archivo de imagen del directorio de datos + */ + + /* + * Modificar: + * Casuística: + * 1: No existe imagen ni antes ni ahora. + * 2: No existía imagen y ahora sí + * 3: Existía imagen y ahora no + * 4: Existía imagen antes y ahora y es la misma + * 5: Existía imagen antes y ahora y es distinta + */ + + } + } protected function modificar() { @@ -667,7 +728,8 @@ class Mantenimiento { '; @@ -692,7 +754,8 @@ class Mantenimiento { $mensaje .= ''; $mensaje .= ''; return $mensaje; - } + } + } ?> \ No newline at end of file diff --git a/Zebra_Image.php b/Zebra_Image.php new file mode 100644 index 0000000..ba59a2a --- /dev/null +++ b/Zebra_Image.php @@ -0,0 +1,1707 @@ + + * @version 2.2.3 (last revision: July 14, 2013) + * @copyright (c) 2006 - 2013 Stefan Gabos + * @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE + * @package Zebra_Image + */ +class Zebra_Image +{ + + /** + * Indicates the file system permissions to be set for newly created images. + * + * Better is to leave this setting as it is. + * + * If you know what you are doing, here is how you can calculate the permission levels: + * + * - 400 Owner Read + * - 200 Owner Write + * - 100 Owner Execute + * - 40 Group Read + * - 20 Group Write + * - 10 Group Execute + * - 4 Global Read + * - 2 Global Write + * - 1 Global Execute + * + * Default is 0755 + * + * @var integer + */ + var $chmod_value; + + /** + * If set to FALSE, images having both width and height smaller than the required width and height, will be left + * untouched ({@link jpeg_quality} and {@link png_compression} will still apply). + * + * Available only for the {@link resize()} method + * + * Default is TRUE + * + * @var boolean + */ + var $enlarge_smaller_images; + + /** + * In case of an error read this property's value to see the error's code. + * + * Possible error codes are: + * + * - 1: source file could not be found + * - 2: source file is not readable + * - 3: could not write target file + * - 4: unsupported source file format + * - 5: unsupported target file format + * - 6: GD library version does not support target file format + * - 7: GD library is not installed! + * - 8: "chmod" command is disabled via configuration + * + * Default is 0 (no error). + * + * @var integer + */ + var $error; + + /** + * Indicates the quality of the output image (better quality means bigger file size). + * + * Used only if the file at {@link target_path} is a JPG/JPEG image. + * + * Range is 0 - 100 + * + * Default is 85 + * + * @var integer + */ + var $jpeg_quality; + + /** + * Indicates the compression level of the output image (lower compression means bigger file size). + * + * Available only if PHP version is 5.1.2+, and only if the file at {@link target_path} is a PNG image. It will be + * ignored otherwise. + * + * Range is 0 - 9 + * + * Default is 9 + * + * @since 2.2 + * + * @var integer + */ + var $png_compression; + + /** + * Specifies whether, upon resizing, images should preserve their aspect ratio. + * + * Available only for the {@link resize()} method + * + * Default is TRUE + * + * @var boolean + */ + var $preserve_aspect_ratio; + + /** + * Indicates whether a target files should preserve the source file's date/time. + * + * Default is TRUE + * + * @since 1.0.4 + * + * @var boolean + */ + var $preserve_time; + + /** + * Indicates whether the target image should have a "sharpen" filter applied to it. + * + * Can be very useful when creating thumbnails and should be used only when creating thumbnails. + * + * The sharpen filter relies on the "imageconvolution" PHP function which is available only for PHP version + * 5.1.0+, and will leave the images unaltered for older versions! + * + * Default is FALSE + * + * @since 2.2 + * + * @var boolean + */ + var $sharpen_images; + + /** + * Path to an image file to apply the transformations to. + * + * Supported file types are GIF, PNG and JPEG. + * + * @var string + */ + var $source_path; + + /** + * Path (including file name) to where to save the transformed image. + * + * Can be a different than {@link source_path} - the type of the transformed image will be as indicated by the + * file's extension (supported file types are GIF, PNG and JPEG). + * + * @var string + */ + var $target_path; + + /** + * Constructor of the class. + * + * Initializes the class and the default properties + * + * @return void + */ + function Zebra_Image() + { + + // set default values for properties + $this->chmod_value = 0755; + + $this->error = 0; + + $this->jpeg_quality = 85; + + $this->png_compression = 9; + + $this->preserve_aspect_ratio = $this->preserve_time = $this->enlarge_smaller_images = true; + + $this->sharpen_images = false; + + $this->source_path = $this->target_path = ''; + + } + + /** + * Applies one or more filters to the image given as {@link source_path} and outputs it as the file specified as + * {@link target_path}. + * + * This method is available only if the {@link http://php.net/manual/en/function.imagefilter.php imagefilter} + * function is available (available from PHP 5+), and will leave images unaltered otherwise. + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // apply the "grayscale" filter + * $img->apply_filter('grayscale'); + * + * // apply the "contrast" filter + * $img->apply_filter('contrast', -20); + * + * + * You can also apply multiple filters at once. In this case, the method requires a single argument, an array of + * arrays, containing the filters and associated arguments, where applicable: + * + * + * // create a sepia effect + * // note how we're applying multiple filters at once + * // each filter is in its own array + * $img->apply_filter(array( + * + * // first we apply the "grayscale" filter + * array('grayscale'), + * + * // then we apply the "colorize" filter with 90, 60, 40 as + * // the values for red, green and blue + * array('colorize', 90, 60, 40), + * + * )); + * + * + * @param string $filter The (case-insensitive) name of the filter to apply. Can be one of the following: + * + * - brightness - changes the brightness of the image; use arg1 + * to set the level of brightness; the range of brightness + * is -255 to 255; + * - colorize - adds (subtracts) specified RGB values to each pixel; + * use arg1, arg2 and arg3 in the + * form of red, green, blue and arg4 for the alpha + * channel. the range for each color is -255 to 255 and + * 0 to 127 for alpha; alpha support is available only + * for PHP 5.2.5+; + * - contrast - changes the contrast of the image; use arg1 + * to set the level of contrast; the range of contrast + * is -100 to 100; + * - gausian_blur - blurs the image using the Gaussian method; + * - grayscale - converts the image into grayscale; + * - edgedetect - uses edge detection to highlight the edges in the image; + * - emboss - embosses the image; + * - mean_removal - uses mean removal to achieve a "sketchy" effect; + * - negate - reverses all the colors of the image; + * - pixelate - applies pixelation effect to the image, use arg1 + * to set the block size and arg2 to set the + * pixelation effect mode; this filter is available + * only for PHP 5.3.0+; + * - selective_blur - blurs the image; + * - smooth - makes the image smoother. Use arg1 to set the + * level of smoothness. applies a 9-cell convolution matrix + * where center pixel has the weight of arg1 and + * others weight of 1.0. the result is normalized by dividing + * the sum with arg1 + 8.0 (sum of the matrix). + * any float is accepted; + * + * @param mixed $arg1 Used by the following filters: + * - brightness - sets the brightness level (-255 to 255) + * - contrast - sets the contrast level (-100 to 100) + * - colorize - sets the value of the red component (-255 to 255) + * - smooth - sets the smoothness level + * - pixelate - sets the block size, in pixels + * + * @param mixed $arg2 Used by the following filters: + * - colorize - sets the value of the green component (-255 to 255) + * - pixelate - whether to use advanced pixelation effect or not (defaults to FALSE). + * + * @param mixed $arg3 Used by the following filters: + * - colorize - sets the value of the blue component (-255 to 255) + * + * @param mixed $arg4 Used by the following filters: + * - colorize - alpha channel; a value between 0 and 127. 0 indicates + * completely opaque while 127 indicates completely + * transparent. + * + * @since 2.2.2 + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If {@link http://php.net/manual/en/function.imagefilter.php imagefilter} is not + * available the method will return FALSE without setting an {@link error} code. + * + * If the requested filter doesn't exist, or invalid arguments are passed, the method + * will trigger a warning. + * + * If FALSE is returned and you are sure that + * {@link http://php.net/manual/en/function.imagefilter.php imagefilter} exists and that + * the requested filter is valid, check the {@link error} property to see the error code. + */ + function apply_filter($filter, $arg1 = '', $arg2 = '', $arg3 = '', $arg4 = '') + { + + // if "imagefilter" function exists and the requested filter exists + if (function_exists('imagefilter')) + + // if image resource was successfully created + if ($this->_create_from_source()) { + + // prepare the target image + $target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1); + + // copy the original image + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + 0, + 0, + 0, + 0, + $this->source_width, + $this->source_height, + $this->source_width, + $this->source_height + + ); + + // if multiple filters are to be applied at once + if (is_array($filter)) { + + // iterate through the filters + foreach ($filter as $arguments) + + // if filter exists + if (defined('IMG_FILTER_' . strtoupper($arguments[0]))) { + + // try to apply the filter... + if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($arguments[0]))), array_slice($arguments, 1)))) + + // ...and trigger an error if the filter could not be applied + trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING); + + // if filter doesn't exists, trigger an error + } else trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING); + + // if a single filter is to be applied and it is available + } elseif (defined('IMG_FILTER_' . strtoupper($filter))) { + + // get all the arguments passed to the method + $arguments = func_get_args(); + + // try to apply the filter... + if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($filter))), array_slice($arguments, 1)))) + + // ...and trigger an error if the filter could not be applied + trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING); + + // if filter doesn't exists, trigger an error + } else trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING); + + // write image + return $this->_write_image($target_identifier); + + } + + // if script gets this far, return false + // note that we do not set the error level as it has been already set + // by the _create_from_source() method earlier, if the case + return false; + + } + + /** + * Crops a portion of the image given as {@link source_path} and outputs it as the file specified as {@link target_path}. + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // crop a rectangle of 100x100 pixels, starting from the top-left corner + * $img->crop(0, 0, 100, 100); + * + * + * @param integer $start_x x coordinate to start cropping from + * + * @param integer $start_y y coordinate to start cropping from + * + * @param integer $end_x x coordinate where to end the cropping + * + * @param integer $end_y y coordinate where to end the cropping + * + * @since 1.0.4 + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error code. + */ + function crop($start_x, $start_y, $end_x, $end_y) + { + + // this method might be also called internally + // in this case, there's a fifth argument that points to an already existing image identifier + $args = func_get_args(); + + // if fifth argument exists + if (isset($args[4]) && is_resource($args[4])) { + + // that it is the image identifier that we'll be using further on + $this->source_identifier = $args[4]; + + // set this to true so that the script will continue to execute at the next IF + $result = true; + + // if method is called as usually + // try to create an image resource from source path + } else $result = $this->_create_from_source(); + + // if image resource was successfully created + if ($result !== false) { + + // prepare the target image + $target_identifier = $this->_prepare_image($end_x - $start_x, $end_y - $start_y, -1); + + // crop the image + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + 0, + 0, + $start_x, + $start_y, + $end_x - $start_x, + $end_y - $start_y, + $end_x - $start_x, + $end_y - $start_y + + ); + + // write image + return $this->_write_image($target_identifier); + + } + + // if script gets this far, return false + // note that we do not set the error level as it has been already set + // by the _create_from_source() method earlier + return false; + + } + + /** + * Flips both horizontally and vertically the image given as {@link source_path} and outputs the resulted image as + * {@link target_path} + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // flip the image both horizontally and vertically + * $img->flip_both(); + * + * + * @since 2.1 + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error code. + */ + function flip_both() + { + + return $this->_flip('both'); + + } + + /** + * Flips horizontally the image given as {@link source_path} and outputs the resulted image as {@link target_path} + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // flip the image horizontally + * $img->flip_horizontal(); + * + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error code. + */ + function flip_horizontal() + { + + return $this->_flip('horizontal'); + + } + + /** + * Flips vertically the image given as {@link source_path} and outputs the resulted image as {@link target_path} + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // flip the image vertically + * $img->flip_vertical(); + * + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error code. + */ + function flip_vertical() + { + + return $this->_flip('vertical'); + + } + + /** + * Resizes the image given as {@link source_path} and outputs the resulted image as {@link target_path}. + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // apply a "sharpen" filter to the resulting images + * $img->sharpen_images = true; + * + * // resize the image to exactly 150x150 pixels, without altering aspect ratio, by using the CROP_CENTER method + * $img->resize(150, 150, ZEBRA_IMAGE_CROP_CENTER); + * + * + * @param integer $width The width to resize the image to. + * + * If set to 0, the width will be automatically adjusted, depending + * on the value of the height argument so that the image preserves + * its aspect ratio. + * + * If {@link preserve_aspect_ratio} is set to TRUE and both this and the + * height arguments are values greater than 0, the image will + * be resized to the exact required width and height and the aspect ratio + * will be preserved - (also see the description for the method + * argument below on how can this be done). + * + * If {@link preserve_aspect_ratio} is set to FALSE, the image will be + * resized to the required width and the aspect ratio will be ignored. + * + * If both width and height are set to 0, a copy of + * the source image will be created ({@link jpeg_quality} and + * {@link png_compression} will still apply). + * + * If either width or height are set to 0, the script + * will consider the value of the {@link preserve_aspect_ratio} to bet set + * to TRUE regardless of its actual value! + * + * @param integer $height The height to resize the image to. + * + * If set to 0, the height will be automatically adjusted, depending + * on the value of the width argument so that the image preserves + * its aspect ratio. + * + * If {@link preserve_aspect_ratio} is set to TRUE and both this and the + * width arguments are values greater than 0, the image will + * be resized to the exact required width and height and the aspect ratio + * will be preserved - (also see the description for the method + * argument below on how can this be done). + * + * If {@link preserve_aspect_ratio} is set to FALSE, the image will be + * resized to the required height and the aspect ratio will be ignored. + * + * If both width and height are set to 0, a copy of + * the source image will be created ({@link jpeg_quality} and + * {@link png_compression} will still apply). + * + * If either height or width are set to 0, the script + * will consider the value of the {@link preserve_aspect_ratio} to bet set + * to TRUE regardless of its actual value! + * + * @param int $method (Optional) Method to use when resizing images to exact width and height + * while preserving aspect ratio. + * + * If the {@link preserve_aspect_ratio} property is set to TRUE and both the + * width and height arguments are values greater than 0, + * the image will be resized to the exact given width and height and the + * aspect ratio will be preserved by using on of the following methods: + * + * - ZEBRA_IMAGE_BOXED - the image will be scalled so that it will + * fit in a box with the given width and height (both width/height will + * be smaller or equal to the required width/height) and then it will + * be centered both horizontally and vertically. The blank area will be + * filled with the color specified by the bgcolor argument. (the + * blank area will be filled only if the image is not transparent!) + * + * - ZEBRA_IMAGE_NOT_BOXED - the image will be scalled so that it + * could fit in a box with the given width and height but will + * not be enclosed in a box with given width and height. The new width/ + * height will be both smaller or equal to the required width/height + * + * - ZEBRA_IMAGE_CROP_TOPLEFT + * - ZEBRA_IMAGE_CROP_TOPCENTER + * - ZEBRA_IMAGE_CROP_TOPRIGHT + * - ZEBRA_IMAGE_CROP_MIDDLELEFT + * - ZEBRA_IMAGE_CROP_CENTER + * - ZEBRA_IMAGE_CROP_MIDDLERIGHT + * - ZEBRA_IMAGE_CROP_BOTTOMLEFT + * - ZEBRA_IMAGE_CROP_BOTTOMCENTER + * - ZEBRA_IMAGE_CROP_BOTTOMRIGHT + * + * For the methods involving crop, first the image is scaled so that both + * its sides are equal or greater than the respective sizes of the bounding + * box; next, a region of required width and height will be cropped from + * indicated region of the resulted image. + * + * Default is ZEBRA_IMAGE_CROP_CENTER + * + * @param hexadecimal $background_color (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the + * blank area. See the method argument. + * + * When set to -1 the script will preserve transparency for transparent GIF + * and PNG images. For non-transparent images the background will be white + * in this case. + * + * Default is #FFFFFF. + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see what went + * wrong + */ + function resize($width = 0, $height = 0, $method = ZEBRA_IMAGE_CROP_CENTER, $background_color = '#FFFFFF') + { + + // if image resource was successfully created + if ($this->_create_from_source()) { + + // if either width or height is to be adjusted automatically + // set a flag telling the script that, even if $preserve_aspect_ratio is set to false + // treat everything as if it was set to true + if ($width == 0 || $height == 0) $auto_preserve_aspect_ratio = true; + + // if aspect ratio needs to be preserved + if ($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) { + + // if height is given and width is to be computed accordingly + if ($width == 0 && $height > 0) { + + // get the original image's aspect ratio + $aspect_ratio = $this->source_width / $this->source_height; + + // the target image's height is as given as argument to the method + $target_height = $height; + + // compute the target image's width, preserving the aspect ratio + $target_width = round($height * $aspect_ratio); + + // if width is given and height is to be computed accordingly + } elseif ($width > 0 && $height == 0) { + + // get the original image's aspect ratio + $aspect_ratio = $this->source_height / $this->source_width; + + // the target image's width is as given as argument to the method + $target_width = $width; + + // compute the target image's height, preserving the aspect ratio + $target_height = round($width * $aspect_ratio); + + // if both width and height are given and ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED methods are to be used + } elseif ($width > 0 && $height > 0 && ($method == 0 || $method == 1)) { + + // compute the horizontal and vertical aspect ratios + $vertical_aspect_ratio = $height / $this->source_height; + $horizontal_aspect_ratio = $width / $this->source_width; + + // if the image's newly computed height would be inside the bounding box + if (round($horizontal_aspect_ratio * $this->source_height < $height)) { + + // the target image's width is as given as argument to the method + $target_width = $width; + + // compute the target image's height so that the image will stay inside the bounding box + $target_height = round($horizontal_aspect_ratio * $this->source_height); + + // otherwise + } else { + + // the target image's height is as given as argument to the method + $target_height = $height; + + // compute the target image's width so that the image will stay inside the bounding box + $target_width = round($vertical_aspect_ratio * $this->source_width); + + } + + // if both width and height are given and image is to be cropped in order to get to the required size + } elseif ($width > 0 && $height > 0 && $method > 1 && $method < 11) { + + // compute the horizontal and vertical aspect ratios + $vertical_aspect_ratio = $this->source_height / $height; + $horizontal_aspect_ratio = $this->source_width / $width; + + // we'll use one of the two + $aspect_ratio = + + $vertical_aspect_ratio < $horizontal_aspect_ratio ? + + $vertical_aspect_ratio : + + $horizontal_aspect_ratio; + + // compute the target image's width, preserving the aspect ratio + $target_width = round($this->source_width / $aspect_ratio); + + // compute the target image's height, preserving the aspect ratio + $target_height = round($this->source_height / $aspect_ratio); + + // for any other case + } else { + + // we will create a copy of the source image + $target_width = $this->source_width; + $target_height = $this->source_height; + + } + + // if aspect ratio does not need to be preserved + } else { + + // compute the target image's width + $target_width = ($width > 0 ? $width : $this->source_width); + + // compute the target image's height + $target_height = ($height > 0 ? $height : $this->source_height); + + } + + // if + if ( + + // all images are to be resized - including images that are smaller than the given width/height + $this->enlarge_smaller_images || + + // smaller images than the given width/height are to be left untouched + // but current image has at leas one side that is larger than the required width/height + ($width > 0 && $height > 0 ? + + ($this->source_width > $width || $this->source_height > $height) : + + ($this->source_width > $target_width || $this->source_height > $target_height) + + ) + + ) { + + // if + if ( + + // aspect ratio needs to be preserved AND + ($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) && + + // both width and height are given + ($width > 0 && $height > 0) && + + // images are to be cropped + ($method > 1 && $method < 11) + + ) { + + // prepare the target image + $target_identifier = $this->_prepare_image($target_width, $target_height, $background_color); + + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + 0, + 0, + 0, + 0, + $target_width, + $target_height, + $this->source_width, + $this->source_height + + ); + + // do the crop according to the required method + switch ($method) { + + // if image needs to be cropped from the top-left corner + case ZEBRA_IMAGE_CROP_TOPLEFT: + + // crop accordingly + return $this->crop( + 0, + 0, + $width, + $height, + $target_identifier // crop this resource instead + ); + + break; + + // if image needs to be cropped from the top-center + case ZEBRA_IMAGE_CROP_TOPCENTER: + + // crop accordingly + return $this->crop( + floor(($target_width - $width) / 2), + 0, + floor(($target_width - $width) / 2) + $width, + $height, + $target_identifier // crop this resource instead + ); + + break; + + // if image needs to be cropped from the top-right corner + case ZEBRA_IMAGE_CROP_TOPRIGHT: + + // crop accordingly + return $this->crop( + $target_width - $width, + 0, + $target_width, + $height, + $target_identifier // crop this resource instead + ); + + break; + + // if image needs to be cropped from the middle-left + case ZEBRA_IMAGE_CROP_MIDDLELEFT: + + // crop accordingly + return $this->crop( + + 0, + floor(($target_height - $height) / 2), + $width, + floor(($target_height - $height) / 2) + $height, + $target_identifier // crop this resource instead + + ); + + break; + + // if image needs to be cropped from the center of the image + case ZEBRA_IMAGE_CROP_CENTER: + + // crop accordingly + return $this->crop( + + floor(($target_width - $width) / 2), + floor(($target_height - $height) / 2), + floor(($target_width - $width) / 2) + $width, + floor(($target_height - $height) / 2) + $height, + $target_identifier // crop this resource instead + + ); + + break; + + // if image needs to be cropped from the middle-right + case ZEBRA_IMAGE_CROP_MIDDLERIGHT: + + // crop accordingly + return $this->crop( + + $target_width - $width, + floor(($target_height - $height) / 2), + $target_width, + floor(($target_height - $height) / 2) + $height, + $target_identifier // crop this resource instead + + ); + + break; + + // if image needs to be cropped from the bottom-left corner + case ZEBRA_IMAGE_CROP_BOTTOMLEFT: + + // crop accordingly + return $this->crop( + + 0, + $target_height - $height, + $width, + $target_height, + $target_identifier // crop this resource instead + + ); + + break; + + // if image needs to be cropped from the bottom-center + case ZEBRA_IMAGE_CROP_BOTTOMCENTER: + + // crop accordingly + return $this->crop( + + floor(($target_width - $width) / 2), + $target_height - $height, + floor(($target_width - $width) / 2) + $width, + $target_height, + $target_identifier // crop this resource instead + + ); + + break; + + // if image needs to be cropped from the bottom-right corner + case ZEBRA_IMAGE_CROP_BOTTOMRIGHT: + + // crop accordingly + return $this->crop( + + $target_width - $width, + $target_height - $height, + $target_width, + $target_height, + $target_identifier // crop this resource instead + + ); + + break; + + } + + // if aspect ratio doesn't need to be preserved or + // it needs to be preserved and method is ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED + } else { + + // prepare the target image + $target_identifier = $this->_prepare_image( + ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $width : $target_width), + ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $height : $target_height), + $background_color + ); + + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($width - $target_width) / 2 : 0), + ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($height - $target_height) / 2 : 0), + 0, + 0, + $target_width, + $target_height, + $this->source_width, + $this->source_height + + ); + + // if script gets this far, write the image to disk + return $this->_write_image($target_identifier); + + } + + // if we get here it means that + // smaller images than the given width/height are to be left untouched + // therefore, we save the image as it is + } else return $this->_write_image($this->source_identifier); + + } + + // if script gets this far return false + // note that we do not set the error level as it has been already set + // by the _create_from_source() method earlier + return false; + + } + + /** + * Rotates the image given as {@link source_path} and outputs the resulted image as {@link target_path}. + * + * + * // include the Zebra_Image library + * require 'path/to/Zebra_Image.php'; + * + * // instantiate the class + * $img = new Zebra_Image(); + * + * // a source image + * $img->source_path = 'path/to/source.ext'; + * + * // path to where should the resulting image be saved + * // note that by simply setting a different extension to the file will + * // instruct the script to create an image of that particular type + * $img->target_path = 'path/to/target.ext'; + * + * // rotate the image 45 degrees, clockwise + * $img->rotate(45); + * + * + * @param double $angle Angle by which to rotate the image clockwise. + * + * Between 0 and 360. + * + * @param mixed $background_color (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the + * uncovered zone after the rotation. + * + * When set to -1 the script will preserve transparency for transparent GIF + * and PNG images. For non-transparent images the background will be white + * in this case. + * + * Default is -1. + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error + * code. + */ + function rotate($angle, $background_color = -1) + { + + // if image resource was successfully created + if ($this->_create_from_source()) { + + // angles are given clockwise but imagerotate works counterclockwise so we need to negate our value + $angle = -$angle; + + // if source image is PNG + if ($this->source_type == IMAGETYPE_PNG && $background_color == -1) { + + // rotate the image + // but if using -1 as background color didn't work (as is the case for PNG8) + if (!($target_identifier = imagerotate($this->source_identifier, $angle, -1))) { + + // we will be using #FFF as the color to fill the uncovered zone after the rotation + $background_color = imagecolorallocate($this->source_identifier, 255, 255, 255); + + // rotate the image + $target_identifier = imagerotate($this->source_identifier, $angle, $background_color); + + } + + // if source image is a transparent GIF + } elseif ($this->source_type == IMAGETYPE_GIF && $this->source_transparent_color_index >= 0) { + + // convert the background color to RGB values + $background_color = $this->_hex2rgb($background_color); + + // allocate the color to the image identifier + $background_color = imagecolorallocate( + + $this->source_identifier, + $background_color['r'], + $background_color['g'], + $background_color['b'] + + ); + + // rotate the image + $this->source_identifier = imagerotate($this->source_identifier, $angle, $background_color); + + // get the width of rotated image + $width = imagesx($this->source_identifier); + + // get the height of rotated image + $height = imagesy($this->source_identifier); + + // create a blank image with the new width and height + // (this intermediary step is for preserving transparency) + $target_identifier = $this->_prepare_image($width, $height, -1); + + // copy the rotated image on to the new one + imagecopyresampled($target_identifier, $this->source_identifier, 0, 0, 0, 0, $width, $height, $width, $height); + + // for the other cases + } else { + + // convert the color to RGB values + $background_color = $this->_hex2rgb($background_color); + + // allocate the color to the image identifier + $background_color = imagecolorallocate( + + $this->source_identifier, + $background_color['r'], + $background_color['g'], + $background_color['b'] + + ); + + // rotate the image + $target_identifier = imagerotate($this->source_identifier, $angle, $background_color); + + } + + // write image + $this->_write_image($target_identifier); + + } + + // if script gets this far return false + // note that we do not set the error level as it has been already set + // by the _create_from_source() method earlier + return false; + + } + + /** + * Returns an array containing the image identifier representing the image obtained from {@link $source_path}, the + * image's width and height and the image's type + * + * @access private + */ + function _create_from_source() + { + + // perform some error checking first + // if the GD library is not installed + if (!function_exists('gd_info')) { + + // save the error level and stop the execution of the script + $this->error = 7; + + return false; + + // if source file does not exist + } elseif (!is_file($this->source_path)) { + + // save the error level and stop the execution of the script + $this->error = 1; + + return false; + + // if source file is not readable + } elseif (!is_readable($this->source_path)) { + + // save the error level and stop the execution of the script + $this->error = 2; + + return false; + + // if target file is same as source file and source file is not writable + } elseif ($this->target_path == $this->source_path && !is_writable($this->source_path)) { + + // save the error level and stop the execution of the script + $this->error = 3; + + return false; + + // try to get source file width, height and type + // and if it founds an unsupported file type + } elseif (!list($this->source_width, $this->source_height, $this->source_type) = @getimagesize($this->source_path)) { + + // save the error level and stop the execution of the script + $this->error = 4; + + return false; + + // if no errors so far + } else { + + // get target file's type based on the file extension + $this->target_type = strtolower(substr($this->target_path, strrpos($this->target_path, '.') + 1)); + + // create an image from file using extension dependant function + // checks for file extension + switch ($this->source_type) { + + // if GIF + case IMAGETYPE_GIF: + + // create an image from file + $identifier = imagecreatefromgif($this->source_path); + + // get the index of the transparent color (if any) + if (($this->source_transparent_color_index = imagecolortransparent($identifier)) >= 0) + + // get the transparent color's RGB values + // we have to mute errors because there are GIF images which *are* transparent and everything + // works as expected, but imagecolortransparent() returns a color that is outside the range of + // colors in the image's pallette... + $this->source_transparent_color = @imagecolorsforindex($identifier, $this->source_transparent_color_index); + + break; + + // if JPEG + case IMAGETYPE_JPEG: + + // create an image from file + $identifier = imagecreatefromjpeg($this->source_path); + + break; + + // if PNG + case IMAGETYPE_PNG: + + // create an image from file + $identifier = imagecreatefrompng($this->source_path); + + // disable blending + imagealphablending($identifier, false); + + break; + + default: + + // if unsupported file type + // note that we call this if the file is not GIF, JPG or PNG even though the getimagesize function + // handles more image types + $this->error = 4; + + return false; + + } + + } + + // if target file has to have the same timestamp as the source image + // save it as a global property of the class + if ($this->preserve_time) $this->source_image_time = filemtime($this->source_path); + + // make available the source image's identifier + $this->source_identifier = $identifier; + + return true; + + } + + /** + * Converts a hexadecimal representation of a color (i.e. #123456 or #AAA) to a RGB representation. + * + * The RGB values will be a value between 0 and 255 each. + * + * @param string $color Hexadecimal representation of a color (i.e. #123456 or #AAA). + * + * @param string $default_on_error Hexadecimal representation of a color to be used in case $color is not + * recognized as a hexadecimal color. + * + * @return array Returns an associative array with the values of (R)ed, (G)reen and (B)lue + * + * @access private + */ + function _hex2rgb($color, $default_on_error = '#FFFFFF') + { + + // if color is not formatted correctly + // use the default color + if (preg_match('/^#?([a-f]|[0-9]){3}(([a-f]|[0-9]){3})?$/i', $color) == 0) $color = $default_on_error; + + // trim off the "#" prefix from $background_color + $color = ltrim($color, '#'); + + // if color is given using the shorthand (i.e. "FFF" instead of "FFFFFF") + if (strlen($color) == 3) { + + $tmp = ''; + + // take each value + // and duplicate it + for ($i = 0; $i < 3; $i++) $tmp .= str_repeat($color[$i], 2); + + // the color in it's full, 6 characters length notation + $color = $tmp; + + } + + // decimal representation of the color + $int = hexdec($color); + + // extract and return the RGB values + return array( + + 'r' => 0xFF & ($int >> 0x10), + 'g' => 0xFF & ($int >> 0x8), + 'b' => 0xFF & $int + + ); + + } + + /** + * Flips horizontally or vertically or both ways the image given as {@link source_path}. + * + * @since 2.1 + * + * @access private + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error code. + */ + function _flip($orientation) + { + + // if image resource was successfully created + if ($this->_create_from_source()) { + + // prepare the target image + $target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1); + + // flip according to $orientation + switch ($orientation) { + + case 'horizontal': + + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + 0, + 0, + ($this->source_width - 1), + 0, + $this->source_width, + $this->source_height, + -$this->source_width, + $this->source_height + + ); + + break; + + case 'vertical': + + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + 0, + 0, + 0, + ($this->source_height - 1), + $this->source_width, + $this->source_height, + $this->source_width, + -$this->source_height + + ); + + break; + + case 'both': + + imagecopyresampled( + + $target_identifier, + $this->source_identifier, + 0, + 0, + ($this->source_width - 1), + ($this->source_height - 1), + $this->source_width, + $this->source_height, + -$this->source_width, + -$this->source_height + + ); + + break; + + } + + // write image + return $this->_write_image($target_identifier); + + } + + // if script gets this far, return false + // note that we do not set the error level as it has been already set + // by the _create_from_source() method earlier + return false; + + } + + /** + * Creates a blank image of given width, height and background color. + * + * @param integer $width Width of the new image. + * + * @param integer $height Height of the new image. + * + * @param string $background_color (Optional) The hexadecimal color of the background. + * + * Can also be -1 case in which the script will try to create a transparent + * image, if possible. + * + * Default is "#FFFFFF". + * + * @return Returns the identifier of the newly created image. + * + * @access private + */ + function _prepare_image($width, $height, $background_color = '#FFFFFF') + { + + // create a blank image + $identifier = imagecreatetruecolor((int)$width <= 0 ? 1 : (int)$width, (int)$height <= 0 ? 1 : (int)$height); + + // if we are creating a PNG image + if ($this->target_type == 'png' && $background_color == -1) { + + // disable blending + imagealphablending($identifier, false); + + // allocate a transparent color + $transparent_color = imagecolorallocatealpha($identifier, 0, 0, 0, 127); + + // fill the image with the transparent color + imagefill($identifier, 0, 0, $transparent_color); + + //save full alpha channel information + imagesavealpha($identifier, true); + + // if source image is a transparent GIF + } elseif ($this->target_type == 'gif' && $background_color == -1 && $this->source_transparent_color_index >= 0) { + + // allocate the source image's transparent color also to the new image resource + $transparent_color = imagecolorallocate( + $identifier, + $this->source_transparent_color['red'], + $this->source_transparent_color['green'], + $this->source_transparent_color['blue'] + ); + + // fill the background of the new image with transparent color + imagefill($identifier, 0, 0, $transparent_color); + + // from now on, every pixel having the same RGB as the transparent color will be transparent + imagecolortransparent($identifier, $transparent_color); + + // for other image types + } else { + + // if transparent background color specified, revert to white + if ($background_color == -1) $background_color = '#FFFFFF'; + + // convert hex color to rgb + $background_color = $this->_hex2rgb($background_color); + + // prepare the background color + $background_color = imagecolorallocate($identifier, $background_color['r'], $background_color['g'], $background_color['b']); + + // fill the image with the background color + imagefill($identifier, 0, 0, $background_color); + + } + + // return the image's identifier + return $identifier; + + } + + /** + * Sharpens images. Useful when creating thumbnails. + * + * Code taken from the comments at {@link http://docs.php.net/imageconvolution}. + * + * This function will yield a result only for PHP version 5.1.0+ and will leave the image unaltered for older + * versions! + * + * @param $identifier identifier An image identifier + * + * @access private + */ + function _sharpen_image($image) + { + + // if the "sharpen_images" is set to true and we're running an appropriate version of PHP + // (the "imageconvolution" is available only for PHP 5.1.0+) + if ($this->sharpen_images && version_compare(PHP_VERSION, '5.1.0') >= 0) { + + // the convolution matrix as an array of three arrays of three floats + $matrix = array( + array(-1.2, -1, -1.2), + array(-1, 20, -1), + array(-1.2, -1, -1.2), + ); + + // the divisor of the matrix + $divisor = array_sum(array_map('array_sum', $matrix)); + + // color offset + $offset = 0; + + // sharpen image + imageconvolution($image, $matrix, $divisor, $offset); + + } + + // return the image's identifier + return $image; + + } + + /** + * Creates a new image from given image identifier having the extension as specified by {@link target_path}. + * + * @param $identifier identifier An image identifier + * + * @return boolean Returns TRUE on success or FALSE on error. + * + * If FALSE is returned, check the {@link error} property to see the error code. + * + * @access private + */ + function _write_image($identifier) + { + + // sharpen image if it's required + $this->_sharpen_image($identifier); + + // image saving process goes according to required extension + switch ($this->target_type) { + + // if GIF + case 'gif': + + // if GD support for this file type is not available + // in version 1.6 of GD the support for GIF files was dropped see + // http://php.net/manual/en/function.imagegif.php#function.imagegif.notes + if (!function_exists('imagegif')) { + + // save the error level and stop the execution of the script + $this->error = 6; + + return false; + + // if, for some reason, file could not be created + } elseif (@!imagegif($identifier, $this->target_path)) { + + // save the error level and stop the execution of the script + $this->error = 3; + + return false; + + } + + break; + + // if JPEG + case 'jpg': + case 'jpeg': + + // if GD support for this file type is not available + if (!function_exists('imagejpeg')) { + + // save the error level and stop the execution of the script + $this->error = 6; + + return false; + + // if, for some reason, file could not be created + } elseif (@!imagejpeg($identifier, $this->target_path, $this->jpeg_quality)) { + + // save the error level and stop the execution of the script + $this->error = 3; + + return false; + + } + + break; + + // if PNG + case 'png': + + // save full alpha channel information + imagesavealpha($identifier, true); + + // if GD support for this file type is not available + if (!function_exists('imagepng')) { + + // save the error level and stop the execution of the script + $this->error = 6; + + return false; + + // if, for some reason, file could not be created + } elseif (@!imagepng($identifier, $this->target_path, $this->png_compression)) { + + // save the error level and stop the execution of the script + $this->error = 3; + + return false; + + } + + break; + + // if not a supported file extension + default: + + // save the error level and stop the execution of the script + $this->error = 5; + + return false; + + } + + // get a list of functions disabled via configuration + $disabled_functions = @ini_get('disable_functions'); + + // if the 'chmod' function is not disabled via configuration + if ($disabled_functions == '' || strpos('chmod', $disabled_functions) === false) { + + // chmod the file + chmod($this->target_path, intval($this->chmod_value, 8)); + + // save the error level + } else $this->error = 8; + + // if target file has to have the same timestamp as the source image + if ($this->preserve_time && isset($this->source_image_time)) { + + // touch the newly created file + @touch($this->target_path, $this->source_image_time); + + } + + // return true + return true; + + } + +}