<?php /* * File: SimpleImage.php (Not Really) * Author: Rumverse, Simon Jarvis * Copyright: 2006 Simon Jarvis, 2011-2012 Rumverse * Date: 08/11/06 * Last Modified: 02/16/2012 * Link: http://www.white-hat-web-design.co.uk/articles/php-image-resizing.php * Link: http://ulaptech.blogspot.com/2012/03/not-so-simple-image-php-object.html * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * http://www.gnu.org/licenses/gpl.html * * rumverse: added support for daisy-chaining via making sure that there's always * a version of the original, added additional get methods, added background, added * layer support * */ class SimpleImage { /** * Originally loaded image * * @var resource */ protected $_imageOri; /** * Transformed image buffer * * @var resource */ protected $_image; /** * List of SimpleImage instances which can be used as * * @var array */ protected $_layers; /** * Should be used as the background of the image * * @var SimpleImage */ protected $_background; /** * In layered mode, is image centered or not? * It's true by default. * * @var bool */ protected $_centered = true; /** * Horizontal alignment, center, left, right * * @var string */ protected $_align; /** * Vertical alignment, center, top, bottom * * @var string */ protected $_valign; /** * Image type - IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG * * @var int */ protected $_image_type; protected $_sizeInfo; protected $_validMime = array('image/jpeg' => self::IMAGEJPEG, 'image/jpg' => self::IMAGEJPEG, 'image/png' => self::IMAGEPNG, 'image/gif' => self::IMAGEGIF); const IMAGEJPEG = 'image/jpeg'; const IMAGEGIF = 'image/gif'; const IMAGEPNG = 'image/png'; /** * x-point position relative to destination image xy plane if object * is used as a layer by another instance of SimpleImage * * @var int */ protected $_layer_xpos = 0; /** * y-point position relative to destination image xy plane if object * is used as a layer by another instance of SimpleImage * * @var int */ protected $_layer_ypos = 0; /** * x-point position of this object's xy plane to start copying from when * used as a layer of another instance of SimpleImage * * @var int */ protected $_layer_xOffset = 0; /** * y-point position of this object's xy plane to start copying from when * used as a layer of another instance of SimpleImage * * @var int */ protected $_layer_yOffset = 0; public function __construct($filename = null) { if (!empty($filename) && is_string($filename)) { $this->load($filename); } } public function load($filename) { if (!is_file($filename)) { trigger_error("Warning: $filename not found", E_USER_WARNING); return false; } $image_info = getimagesize($filename, $additional_info); if (!isset($this->_validMime[$image_info['mime']])) { trigger_error("Warning: file type {$image_info['mime']} not yet supported.", E_USER_WARNING); return false; } $this->_sizeInfo = array_merge($image_info, $additional_info); $this->_image_type = $image_info[2]; if( $this->_image_type == IMAGETYPE_JPEG ) { try { $resource = imagecreatefromjpeg($filename); if(!is_resource($resource)) { trigger_error("Failed to load image but no exceptions raised: {$filename}\n", E_USER_WARNING); return false; } } catch(Exception $e) { trigger_error("Invalid image: {$filename} - {$e->getMessage}\n", E_USER_ERROR); return false; } $this->_image = $resource; $this->_imageOri = imagecreatefromjpeg($filename); } elseif( $this->_image_type == IMAGETYPE_GIF ) { try { $resource = imagecreatefromgif($filename); if(!is_resource($resource)) { trigger_error("Failed to load image but no exceptions raised: {$filename}\n", E_USER_WARNING); return false; } } catch(Exception $e) { trigger_error("Invalid image: {$filename} - {$e->getMessage}\n", E_USER_ERROR); return false; } $this->_image = $resource; $this->_imageOri = imagecreatefromgif($filename); } elseif( $this->_image_type == IMAGETYPE_PNG ) { try { $resource = imagecreatefrompng($filename); if(!is_resource($resource)) { error_log($filename . "\n", 3, 'failed-load-image.txt'); trigger_error("Failed to load image but no exceptions raised: {$filename}\n", E_USER_WARNING); return false; } } catch(Exception $e) { trigger_error("Invalid image: {$filename} - {$e->getMessage}\n", E_USER_ERROR); return false; } $this->_image = $resource; $this->_imageOri = imagecreatefrompng($filename); } return true; } public function addLayer(SimpleImage $layer = null) { if (!empty($layer) && $layer instanceof SimpleImage) { $this->_layers[] = $layer; } return $this; } public function hasLayers() { if (!empty($this->_layers) && $this->_layers[0] instanceof SimpleImage ) { return true; } } public function getValign() { return $this->_valign; } public function setValign($valign = 'center') { if (!empty($valign) && is_string($valign) && in_array($valign, array('center','top','bottom'))) { $this->_valign = $valign; } return $this; } public function getAlign() { return $this->_align; } public function setAlign($valign = 'center') { if (!empty($valign) && is_string($valign) && in_array($valign, array('center','left','right'))) { $this->_align = $valign; } return $this; } public function isCentered() { if ($this->_centered) { return true; } } public function setCentered($enable = true) { $this->_centered = $enable; return $this; } /** * Set the x-position of this object to the destination object * where it is being used as a layer. * * @param int $x * @return $this */ public function setLayerXpos($x) { if (!empty($x)) { $this->_layer_xpos = (integer) $x; } return $this; } /** * Set the y-position of this object to the destination object * where it is being used as a layer. * * @param int $y * @return $this; */ public function setLayerYpos($y) { if (!empty($y)) { $this->_layer_ypos = (integer) $y; } return $this; } /** * Get the x-position of this object based on the destination object * where it is being used as a layer. * * @return int */ public function getLayerXpos($reference = null) { if (empty($this->_layer_xpos)) { if (empty($reference) && $reference instanceof SimpleImage ) { $reference = $this; } //check, for centering, will be overwritten by other positional properties like valign, align, xpos, ypos if ($this->isCentered()) { $xDelta = $reference->getWidth() - $this->getWidth(false); $destXpos = ceil($xDelta/2); } if ($this->getAlign()) { $align = $this->getAlign(); switch ($align) { case 'left': $destXpos = 0; break; case 'center': $xDelta = $reference->getWidth() - $this->getWidth(false); $destXpos = ceil($xDelta/2); break; case 'right': $destXpos = $reference->getWidth() - $this->getWidth(false); break; } } $this->_layer_xpos = $destXpos; } return $this->_layer_xpos; } /** * Set the y-position of this object to the destination object * where it is being used as a layer. * * * @param SimpleImage $reference The image where it belongs to as a layer. NULL indicates that it is not a layer of anything but itself. * @return int */ public function getLayerYpos($reference = null) { if (empty($this->_layer_ypos)) { if (empty($reference) && $reference instanceof SimpleImage ) { $reference = $this; } //check, for centering, will be overwritten by other positional properties like valign, align, xpos, ypos if ($this->isCentered()) { $yDelta = $reference->getHeight() - $this->getHeight(false); $destYpos = floor($yDelta/2); } if ($this->getValign()) { $valign = $this->getValign(); switch ($valign) { case 'top': $destYpos = 0; break; case 'center': $yDelta = $reference->getHeight() - $this->getHeight(false); $destYpos = floor($yDelta/2); break; case 'bottom': $destYpos = $reference->getHeight() - $this->getHeight(false); } } $this->_layer_ypos = $destYpos; } return $this->_layer_ypos; } /** * Get the x-position where to start copying on the xy plane of this object * when treated as layer of another SimpleImage object * * @return int */ public function getLayerXOffset() { return $this->_layer_xOffset; } /** * Get the y-position where to start copying on the xy plane of this object * when treated as layer of another SimpleImage object * * @return int */ public function getLayerYOffset() { return $this->_layer_yOffset; } /** * Set the x-position where to start copying on the xy plane of this object * when treated as layer of another SimpleImage object * * @return $this */ public function setLayerXOffset($x) { if (!empty($x)) { $this->_layer_xOffset = (integer) $x; } return $this; } /** * Set the x-position where to start copying on the xy plane of this object * when treated as layer of another SimpleImage object * * @return $this */ public function setLayerYOffset($y) { if (!empty($y)) { $this->_layer_yOffset = (integer) $y; } return $this; } public function getImgResourceOri() { return $this->_imageOri; } public function getImgResource() { return $this->_image; } public function getSizeInfo() { return $this->_sizeInfo; } /** * buffer for merged image resource * * @var resource */ protected $_imageMerged; /** * When there are layers, return a merge version of the image * * @param bool $useSource * @return resource */ public function getImageResourceMerged($useSource = true) { if ($this->hasLayers()) { $new_layered_image = imagecreatetruecolor($this->getWidth(), $this->getHeight()); $old_image = ($useSource) ? $this->_imageOri : $this->_image; imagecopyresampled($new_layered_image, $old_image, 0, 0, 0, 0, $this->getWidth(), $this->getHeight(), $this->getWidth(), $this->getHeight()); foreach ($this->_layers as $key=>$layer) { if ($layer instanceof SimpleImage) { $destXpos = 0; $destYpos = 0; $destXpos = $layer->getLayerXpos($this); $destYpos = $layer->getLayerYpos($this); imagecopymerge($new_layered_image, //dest $layer->getImgResource(), //source of what to copy $destXpos, //dest x-pos $destYpos, //dest y-pos $layer->getLayerXOffset(), //src x-pos $layer->getLayerYOffset(), //src y-pos $layer->getWidth(false), //src width $layer->getHeight(false), //src height 100); //pct is percent merge which affects transparency etc } } $this->_imageMerged = $new_layered_image; } else { return $this->_image; } return $this->_imageMerged; } public function save($filename, $image_type=IMAGETYPE_JPEG, $compression=75, $permissions=null) { if( $image_type == IMAGETYPE_JPEG ) { try { if ($this->hasLayers()) { imagejpeg($this->getImageResourceMerged(), $filename, $compression); } else { imagejpeg($this->getImgResource(), $filename, $compression); } return true; } catch(Exception $e) { echo "Failed to save image: {$filename} - {$e->getMessage}\n"; trigger_error("Failed to save image: {$filename} - {$e->getMessage}\n", E_USER_ERROR); return false; } } elseif( $image_type == IMAGETYPE_GIF ) { try { if ($this->hasLayers()) { imagegif($this->getImageResourceMerged(), $filename); } else { imagegif($this->getImgResource(), $filename); } return true; } catch(Exception $e) { echo "Failed to save image: {$filename} - {$e->getMessage}\n"; trigger_error("Failed to save image: {$filename} - {$e->getMessage}\n", E_USER_ERROR); return false; } } elseif( $image_type == IMAGETYPE_PNG ) { try { if ($this->hasLayers()) { imagepng($this->getImageResourceMerged(), $filename); } else { imagepng($this->getImgResource(), $filename); } return true; } catch(Exception $e) { echo "Failed to save image: {$filename} - {$e->getMessage}\n"; trigger_error("Failed to save image: {$filename} - {$e->getMessage}\n", E_USER_ERROR); return false; } } if( $permissions != null) { chmod($filename, $permissions); } if (is_file($filename)) { //if saved, the original file resource will then be removed from buffer and the newly saved one becomes the original $this->refresh(); return true; } return false; } public function refresh() { imagedestroy($this->_imageOri); $this->_imageOri = $this->_image; } public function output($image_type=IMAGETYPE_JPEG) { if( $image_type == IMAGETYPE_JPEG ) { header("Content-Type: ". self::IMAGEJPEG); imagejpeg($this->_image); } elseif( $image_type == IMAGETYPE_GIF ) { header("Content-Type: ". self::IMAGEGIF); imagegif($this->_image); } elseif( $image_type == IMAGETYPE_PNG ) { header("Content-Type: ". self::IMAGEPNG); imagepng($this->_image); } } public function getWidth($useSource = true) { if ($useSource) { return imagesx($this->_imageOri); } else { return imagesx($this->_image); } } public function getHeight($useSource = true) { if ($useSource) { return imagesy($this->_imageOri); } else { return imagesy($this->_image); } } public function resizeToHeight($height, $useSource = true) { $ratio = $height / $this->getHeight(); $width = $this->getWidth() * $ratio; $this->resize($width, $height, $useSource); return $this; } public function resizeToWidth($width, $useSource = true) { $ratio = $width / $this->getWidth(); $height = $this->getHeight() * $ratio; $this->resize($width, $height, $useSource); return $this; } public function scale($scale, $useSource = true) { $width = $this->getWidth() * $scale/100; $height = $this->getheight() * $scale/100; $this->resize($width, $height, $useSource); return $this; } public function resize($width, $height, $useSource = true) { $new_image = imagecreatetruecolor($width, $height); $old_image = ($useSource) ? $this->_imageOri : $this->_image; imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight()); $this->_image = $new_image; return $this; } } ?>
Tuesday, March 20, 2012
A Not So Simple Image PHP Object
Extending the functionality of the original SimpleImage.php PHP class to include method daisy-chaining, n-level layering using different object instances and background image support, SimpleImage is can be not so simple anymore. Here's the code:
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment