Implemented image adapters for GD and ImageMagick
authorAlexander Ebert <ebert@woltlab.com>
Tue, 26 Jul 2011 16:06:58 +0000 (18:06 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 26 Jul 2011 16:06:58 +0000 (18:06 +0200)
Image adapters have been tested during development, but needs some more real world examples to ensure consistent and desired behavior.

The ImageHandler-class is still outstanding, will be included with the upcoming commits, leaving the image adapters almost useless for now.

wcfsetup/install/files/lib/system/image/adapter/GDImageAdapter.class.php
wcfsetup/install/files/lib/system/image/adapter/IImageAdapter.class.php
wcfsetup/install/files/lib/system/image/adapter/ImageAdapter.class.php
wcfsetup/install/files/lib/system/image/adapter/ImagickImageAdapter.class.php

index 775901234b1fca7a044808f83caebb359183b9c9..64e077205cf0b6433fc0415a666bb0585676aac1 100644 (file)
@@ -1,5 +1,22 @@
 <?php
-class GDImageAdapter {
+namespace wcf\system\image\adapter;
+
+/**
+ * Image adapter for bundled GD imaging library.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.image.adapter
+ * @category   Community Framework
+ */
+class GDImageAdapter implements IImageAdapter {
+       /**
+        * active color
+        */     
+       protected $color = null;
+       
        /**
         * image height
         * @var integer
@@ -25,10 +42,7 @@ class GDImageAdapter {
        protected $width = 0;
        
        /**
-        * Loads an image from a resource.
-        * 
-        * @param       resource        $image
-        * @param       integer         $type
+        * @see wcf\system\image\adapter\IImageAdapter::load()
         */
        public function load($image, $type = '') {
                if (!is_resource($image)) {
@@ -47,9 +61,7 @@ class GDImageAdapter {
        }
        
        /**
-        * Loads an image from file.
-        * 
-        * @param       string          $file
+        * @see wcf\system\image\adapter\IImageAdapter::loadFile()
         */     
        public function loadFile($file) {
                list($this->width, $this->height, $this->type) = getImageSize($file);
@@ -74,18 +86,9 @@ class GDImageAdapter {
        }
        
        /**
-        * Creates a thumbnail from previously loaded image.
-        * 
-        * @param       integer         $maxWidth
-        * @param       integer         $maxHeight
-        * @param       boolean         $obtainDimensions
-        * @return      resource
+        * @see wcf\system\image\adapter\IImageAdapter::createThumbnail()
         */     
        public function createThumbnail($maxWidth, $maxHeight, $obtainDimensions = true) {
-               if ($maxWidth > $this->width || $maxHeight > $this->height) {
-                       throw new SystemException("Dimensions for thumbnail can not exceed image dimensions.");
-               }
-               
                $width = $height = $x = $y = 0;
                
                if ($obtainDimensions) {
@@ -122,26 +125,9 @@ class GDImageAdapter {
        }
        
        /**
-        * Clips a part of currently loaded image, overwrites image resource within instance.
-        * 
-        * @param       integer         $originX
-        * @param       integer         $originY
-        * @param       integer         $width
-        * @param       integer         $height
-        * @see wcf\system\image\adapter\GDImageAdapter::getImage()
+        * @see wcf\system\image\adapter\IImageAdapter::clip()
         */
        public function clip($originX, $originY, $width, $height) {
-               // validate if coordinates and size are within bounds
-               if ($originX < 0 || $originY < 0) {
-                       throw new SystemException("Clipping an image requires valid offsets, an offset below zero is invalid.");
-               }
-               if ($width <= 0 || $height <= 0) {
-                       throw new SystemException("Clipping an image requires valid dimensions, width or height below or equal zero are invalid.");
-               }
-               if ((($originX + $width) > $this->width) || (($originY + $height) > $this->height)) {
-                       throw new SystemException("Offset and dimension can not exceed image dimensions.");
-               }
-               
                $image = imageCreateTrueColor($width, $height);
                imageAlphaBlending($image, false);
                
@@ -152,25 +138,9 @@ class GDImageAdapter {
        }
        
        /**
-        * Resizes an image with optional scaling, overwrites image resource within instance.
-        * 
-        * @param       integer         $originX
-        * @param       integer         $originY
-        * @param       integer         $originWidth
-        * @param       integer         $originHeight
-        * @param       integer         $targetX
-        * @param       integer         $targetY
-        * @param       integer         $targetWidth
-        * @param       integer         $targetHeight
-        * @see wcf\system\image\adapter\GDImageAdapter::getImage()
+        * @see wcf\system\image\adapter\IImageAdapter::resize()
         */
        public function resize($originX, $originY, $originWidth, $originHeight, $targetX = 0, $targetY = 0, $targetWidth = 0, $targetHeight = 0) {
-               // use origin dimensions if target dimensions are both zero
-               if ($targetWidth == 0 && $targetHeight == 0) {
-                       $targetWidth = $originWidth;
-                       $targetHeight = $originHeight;
-               }
-               
                $image = imageCreateTrueColor($targetWidth, $targetHeight);
                imageAlphaBlending($image, false);
                
@@ -181,60 +151,43 @@ class GDImageAdapter {
        }
        
        /**
-        * Draws a rectangle, overwrites image resource within instance.
-        * 
-        * @param       integer         $startX
-        * @param       integer         $startY
-        * @param       integer         $endX
-        * @param       integer         $endY
-        * @param       integer         $color
-        * @see wcf\system\image\adapter\GDImageAdapter::getColor()
-        * @see wcf\system\image\adapter\GDImageAdapter::getImage()
+        * @see wcf\system\image\adapter\IImageAdapter::drawRectangle()
         */
-       public function drawRectangle($startX, $startY, $endX, $endY, $color) {
-               imageFilledRectangle($this->image, $startX, $startY, $endX, $endY, $color);
+       public function drawRectangle($startX, $startY, $endX, $endY) {
+               imageFilledRectangle($this->image, $startX, $startY, $endX, $endY, $this->color);
        }
        
        /**
-        * Draws a line of text, overwrites image resource within instance.
-        * 
-        * @param       string          $string
-        * @param       integer         $x
-        * @param       integer         $y
-        * @param       integer         $color
-        * @param       integer         $font
-        * @see wcf\system\image\adapter\GDImageAdapter::getColor()
-        * @see wcf\system\image\adapter\GDImageAdapter::getImage()
+        * @see wcf\system\image\adapter\IImageAdapter::drawText()
         */
-       public function drawText($string, $x, $y, $color, $font = 3) {
-               imageString($this->image, $font, $x, $y, $string, $color);
+       public function drawText($string, $x, $y) {
+               imageString($this->image, 3, $x, $y, $string, $this->color);
        }
        
        /**
-        * Creates a color value based upon RGB.
-        * 
-        * @param       integer         $red
-        * @param       integer         $green
-        * @param       integer         $blue
-        * @return      integer
+        * @see wcf\system\image\adapter\IImageAdapter::setColor()
         */     
-       public function getColor($red, $green, $blue) {
-               return imageColorAllocate($this->image, $red, $green, $blue);
+       public function setColor($red, $green, $blue) {
+               $this->color = imageColorAllocate($this->image, $red, $green, $blue);
        }
        
        /**
-        * Writes an image to disk.
-        * 
-        * @param       resource        $image
-        * @param       string          $filename
-        */     
+        * @see wcf\system\image\adapter\IImageAdapter::hasColor()
+        */
+       public function hasColor() {
+               return ($this->color !== null);
+       }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::writeImage()
+        */
        public function writeImage($image, $filename) {
                ob_start();
                
-               if ($this->type == IMAGETYPE_GIF && function_exists('imageGIF')) {
+               if ($this->type == IMAGETYPE_GIF) {
                        imageGIF($image);
                }
-               else if (($this->type == IMAGETYPE_GIF || $this->type == IMAGETYPE_PNG) && function_exists('imagePNG')) {
+               else if ($this->type == IMAGETYPE_PNG) {
                        imagePNG($image);
                }
                else if (function_exists('imageJPEG')) {
@@ -248,9 +201,7 @@ class GDImageAdapter {
        }
        
        /**
-        * Returns image resource.
-        * 
-        * @return      resource
+        * @see wcf\system\image\adapter\IImageAdapter::getImage()
         */
        public function getImage() {
                return $this->image;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fcf235a4892a40d321ad656bdd14cd671f08e19d 100644 (file)
@@ -0,0 +1,133 @@
+<?php
+namespace wcf\system\image\adapter;
+
+/**
+ * Basic interface for all image adapters.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.image.adapter
+ * @category   Community Framework
+ */
+interface IImageAdapter {
+       /**
+        * Loads an image resource.
+        * 
+        * @param       mixed           $image
+        * @param       integer         $type
+        */
+       public function load($image, $type = 0);
+       
+       /**
+        * Loads an image from file.
+        * 
+        * @param       string          $file
+        */
+       public function loadFile($file);
+       
+       /**
+        * Creates a thumbnail from previously loaded image.
+        * 
+        * @param       integer         $maxWidth
+        * @param       integer         $maxHeight
+        * @param       boolean         $obtainDimensions
+        * @return      mixed
+        */
+       public function createThumbnail($maxWidth, $maxHeight, $obtainDimensions = true);
+       
+       /**
+        * Clips a part of currently loaded image, overwrites image resource within instance.
+        * 
+        * @param       integer         $originX
+        * @param       integer         $originY
+        * @param       integer         $width
+        * @param       integer         $height
+        * @see         wcf\system\image\adapter\IImageAdapter::getImage()
+        */
+       public function clip($originX, $originY, $width, $height);
+       
+       /**
+        * Resizes an image with optional scaling, overwrites image resource within instance.
+        * 
+        * @param       integer         $originX
+        * @param       integer         $originY
+        * @param       integer         $originWidth
+        * @param       integer         $originHeight
+        * @param       integer         $targetX
+        * @param       integer         $targetY
+        * @param       integer         $targetWidth
+        * @param       integer         $targetHeight
+        * @see         wcf\system\image\adapter\IImageAdapter::getImage()
+        */
+       public function resize($originX, $originY, $originWidth, $originHeight, $targetX, $targetY, $targetWidth, $targetHeight);
+       
+       /**
+        * Draws a rectangle, overwrites image resource within instance.
+        * 
+        * @param       integer         $startX
+        * @param       integer         $startY
+        * @param       integer         $endX
+        * @param       integer         $endY
+        * @see         wcf\system\image\adapter\IImageAdapter::getImage()
+        * @see         wcf\system\image\adapter\IImageAdapter::setColor()
+        */
+       public function drawRectangle($startX, $startY, $endX, $endY);
+       
+       /**
+        * Draws a line of text, overwrites image resource within instance.
+        * 
+        * @param       string          $string
+        * @param       integer         $x
+        * @param       integer         $y
+        * @see         wcf\system\image\adapter\IImageAdapter::getImage()
+        * @see         wcf\system\image\adapter\IImageAdapter::setColor()
+        */
+       public function drawText($string, $x, $y);
+       
+       /**
+        * Sets active color.
+        * 
+        * @param       integer         $red
+        * @param       integer         $green
+        * @param       integer         $blue
+        */
+       public function setColor($red, $green, $blue);
+       
+       /**
+        * Returns true if a color has been set.
+        * 
+        * @return      boolean
+        */
+       public function hasColor();
+       
+       /**
+        * Writes an image to disk.
+        * 
+        * @param       mixed           $image
+        * @param       string          $filename
+        */
+       public function writeImage($image, $filename);
+       
+       /**
+        * Returns image resource.
+        * 
+        * @return      mixed
+        */
+       public function getImage();
+       
+       /**
+        * Returns image width.
+        * 
+        * @return      integer
+        */
+       public function getWidth();
+       
+       /**
+        * Returns image height
+        * 
+        * @return      integer
+        */
+       public function getHeight();
+}
index 47c1bf18488cf7a20e8ad1c6661e815706f6785a..b2173f6ab8d707f74b9a37f93ef94c2eaf0c4fb6 100644 (file)
@@ -2,17 +2,43 @@
 namespace wcf\system\image\adapter;
 use wcf\system\session\SystemException;
 
-class ImageAdapter {
+/**
+ * Wrapper for image adapters.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.image.adapter
+ * @category   Community Framework
+ */
+class ImageAdapter implements IImageAdapter {
+       /**
+        * IImageAdapter object
+        * 
+        * @var IImageAdapter
+        */
        protected $adapter = null;
        
+       /**
+        * Creates a new ImageAdapter instance.
+        * 
+        * @param       string          $adapterClassName
+        */
        public function __construct($adapterClassName) {
                $this->adapter = new $adapterClassName();
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::load()
+        */
        public function load($image, $type = 0) {
                $this->adapter->load($image, $type);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::loadFile()
+        */
        public function loadFile($file) {
                if (!file_exists($file) || !is_readable($file)) {
                        throw new SystemException("Image '".$file."' is not readable or does not exists.");
@@ -21,6 +47,9 @@ class ImageAdapter {
                $this->adapter->loadFile($file);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::createThumbnail()
+        */
        public function createThumbnail($maxWidth, $maxHeight, $obtainDimensions = true) {
                if ($maxWidth > $this->getWidth() || $maxHeight > $this->getHeight()) {
                        throw new SystemException("Dimensions for thumbnail can not exceed image dimensions.");
@@ -29,6 +58,9 @@ class ImageAdapter {
                return $this->adapter->createThumbnail($maxWidth, $maxHeight, $obtainDimensions);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::clip()
+        */
        public function clip($originX, $originY, $width, $height) {
                // validate if coordinates and size are within bounds
                if ($originX < 0 || $originY < 0) {
@@ -44,6 +76,9 @@ class ImageAdapter {
                $this->adapter->clip($originX, $originY, $width, $height);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::resize()
+        */
        public function resize($originX, $originY, $originWidth, $originHeight, $targetX, $targetY, $targetWidth, $targetHeight) {
                // use origin dimensions if target dimensions are both zero
                if ($targetWidth == 0 && $targetHeight == 0) {
@@ -54,6 +89,9 @@ class ImageAdapter {
                $this->adapter->resize($originX, $originY, $originWidth, $originHeight, $targetX, $targetY, $targetWidth, $targetHeight);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::drawRectangle()
+        */
        public function drawRectangle($startX, $startY, $endX, $endY) {
                if (!$this->adapter->hasColor()) {
                        throw new SystemException("Cannot draw a rectangle unless a color has been specified with setColor().");
@@ -62,6 +100,9 @@ class ImageAdapter {
                $this->adapter->drawRectangle($startX, $startY, $endX, $endY);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::drawText()
+        */
        public function drawText($string, $x, $y) {
                if (!$this->adapter->hasColor()) {
                        throw new SystemException("Cannot draw text unless a color has been specified with setColor().");
@@ -70,14 +111,44 @@ class ImageAdapter {
                $this->adapter->drawText($string, $x, $y);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::setColor()
+        */
        public function setColor($red, $green, $blue) {
                $this->adapter->setColor($red, $green, $blue);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::hasColor()
+        */
+       public function hasColor() {
+               return $this->adapter->hasColor();
+       }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::writeImage()
+        */
+       public function writeImage($image, $filename) {
+               $this->adapter->writeImage($image, $filename);
+       }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getImage()
+        */
+       public function getImage() {
+               return $this->adapter->getImage();
+       }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getWidth()
+        */
        public function getWidth() {
                return $this->adapter->getWidth();
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getHeight()
+        */
        public function getHeight() {
                return $this->adapter->getHeight();
        }
index 497a299a646640d8bf3f275948cf0a2d4d10fc28..2398ad349f939cd7670760f2fd3c6def61350439 100644 (file)
@@ -1,15 +1,53 @@
 <?php
-require_once('GD.php');
+namespace wcf\system\image\adapter;
 
-class ImagickImageAdapter extends GDImageAdapter {
-       protected $imagick = null;
+/**
+ * Image adapter for ImageMagick imaging library.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.image.adapter
+ * @category   Community Framework
+ */
+class ImagickImageAdapter implements IImageAdapter {
+       /**
+        * active color
+        * 
+        * @var \ImagickPixel
+        */
        protected $color = null;
        
+       /**
+        * Imagick object
+        * 
+        * @var \Imagick
+        */
+       protected $imagick = null;
+       
+       /**
+        * image height
+        * @var integer
+        */     
+       protected $height = 0;
        
+       /**
+        * image width
+        * @var integer
+        */     
+       protected $width = 0;
+       
+       /**
+        * Creates a new ImagickImageAdapter.
+        */
        public function __construct() {
                $this->imagick = new \Imagick();
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::load()
+        */
        public function load($image, $type = '') {
                if (!($image instanceof \Imagick)) {
                        throw new SystemException("Object must be an instance of Imagick");
@@ -20,6 +58,9 @@ class ImagickImageAdapter extends GDImageAdapter {
                $this->width = $this->imagick->getImageWidth();
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::loadFile()
+        */
        public function loadFile($file) {
                try {
                        $this->imagick->readImage($file);
@@ -31,6 +72,9 @@ class ImagickImageAdapter extends GDImageAdapter {
                $this->width = $this->imagick->getImageWidth();
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::createThumbnail()
+        */
        public function createThumbnail($maxWidth, $maxHeight, $obtainDimensions = true) {
                $thumbnail = $this->imagick;
                
@@ -40,21 +84,16 @@ class ImagickImageAdapter extends GDImageAdapter {
                return $thumbnail;
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::clip()
+        */
        public function clip($originX, $originY, $width, $height) {
-               // validate if coordinates and size are within bounds
-               if ($originX < 0 || $originY < 0) {
-                       throw new SystemException("Clipping an image requires valid offsets, an offset below zero is invalid.");
-               }
-               if ($width <= 0 || $height <= 0) {
-                       throw new SystemException("Clipping an image requires valid dimensions, width or height below or equal zero are invalid.");
-               }
-               if ((($originX + $width) > $this->width) || (($originY + $height) > $this->height)) {
-                       throw new SystemException("Offset and dimension can not exceed image dimensions.");
-               }
-               
                $this->imagick->cropImage($width, $height, $originX, $originY);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::drawRectangle()
+        */
        public function drawRectangle($startX, $startY, $endX, $endY, $color) {
                $draw = new \ImagickDraw();
                $draw->setFillColor($this->color);
@@ -64,6 +103,9 @@ class ImagickImageAdapter extends GDImageAdapter {
                $this->imagick->drawImage($draw);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::drawText()
+        */
        public function drawText($string, $x, $y, $color, $font = 4) {
                $draw = new \ImagickDraw();
                $draw->setFillColor($this->color);
@@ -74,12 +116,18 @@ class ImagickImageAdapter extends GDImageAdapter {
                $this->imagick->drawImage($draw);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::setColor()
+        */
        public function setColor($red, $green, $blue) {
                $this->color = new \ImagickPixel();
                $this->color->setColor('rgb('.$red.','.$green.','.$blue.')');
                
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::hasColor()
+        */
        public function hasColor() {
                if ($this->color instanceof \ImagickPixel) {
                        return true;
@@ -88,11 +136,31 @@ class ImagickImageAdapter extends GDImageAdapter {
                return false;
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getImage()
+        */
        public function getImage() {
                return $this->imagick;
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::writeImage()
+        */
        public function writeImage($image, $filename) {
                $image->writeImage($filename);
        }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getHeight()
+        */
+       public function getHeight() {
+               return $this->height;
+       }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getWidth()
+        */
+       public function getWidth() {
+               return $this->width;
+       }
 }