Improved image adapters, removed old Thumbnail-class
authorAlexander Ebert <ebert@woltlab.com>
Wed, 27 Jul 2011 13:19:16 +0000 (15:19 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 27 Jul 2011 13:19:16 +0000 (15:19 +0200)
wcfsetup/install/files/lib/system/image/Thumbnail.class.php [deleted file]
wcfsetup/install/files/lib/system/image/adapter/GDImageAdapter.class.php
wcfsetup/install/files/lib/system/image/adapter/ImagickImageAdapter.class.php

diff --git a/wcfsetup/install/files/lib/system/image/Thumbnail.class.php b/wcfsetup/install/files/lib/system/image/Thumbnail.class.php
deleted file mode 100644 (file)
index ab94a82..0000000
+++ /dev/null
@@ -1,447 +0,0 @@
-<?php
-namespace wcf\system\image;
-use wcf\util\FileUtil;
-use wcf\util\StringUtil;
-
-/**
- * Generates a thumbnail of given source file image.
- * 
- * @author     Marcel Werk
- * @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
- * @category   Community Framework
- */
-class Thumbnail {
-       /**
-        * path to source file
-        *
-        * @var string
-        */
-       protected $sourceFile = '';
-       
-       /**
-        * maximum image width
-        *
-        * @var integer
-        */
-       protected $maxWidth = 0;
-       
-       /**
-        * maximum image height
-        *
-        * @var integer
-        */
-       protected $maxHeight = 0;
-       
-       /**
-        * true, to show source information in thumbnail
-        *
-        * @var boolean
-        */
-       protected $appendSourceInfo = false;
-       
-       /**
-        * true, to prefer embedded thumbnails
-        *
-        * @var boolean
-        */
-       protected $useEmbedded = true;
-       
-       /**
-        * true, to generate quadratic thumbnails
-        * 
-        * @var boolean
-        */
-       protected $quadratic = false;
-               
-       /**
-        * mime type of the thumbnail
-        *
-        * @var string
-        */
-       protected $mimeType = '';
-       
-       /**
-        * name of the source image
-        *
-        * @var string
-        */
-       protected $sourceName = '';
-       
-       /**
-        * width of the source image
-        * 
-        * @var integer
-        */
-       protected $sourceWidth = 0;
-       
-       /**
-        * height of the source image
-        * 
-        * @var integer
-        */
-       protected $sourceHeight = 0;
-       
-       /**
-        * file size of the source image
-        * 
-        * @var integer
-        */
-       protected $sourceSize = 0;
-       
-       /**
-        * height of the source information
-        * 
-        * @var integer
-        */
-       protected static $sourceInfoLineHeight = 16;
-       
-       /**
-        * image type of the source image
-        * 
-        * @var integer
-        */
-       protected $imageType = 0;
-       
-       /**
-        * Creates a new Thumbnail object.
-        * 
-        * @param       string          $sourceFile
-        * @param       integer         $maxWidth
-        * @param       integer         $maxHeight
-        * @param       boolean         $appendSourceInfo
-        */
-       public function __construct($sourceFile, $maxWidth = 100, $maxHeight = 100, $appendSourceInfo = false, $sourceName = null, $useEmbedded = true, $quadratic = false) {
-               $this->sourceFile = $sourceFile;
-               $this->maxWidth = $maxWidth;
-               $this->maxHeight = $maxHeight;
-               $this->appendSourceInfo = $appendSourceInfo;
-               $this->useEmbedded = $useEmbedded;
-               $this->quadratic = $quadratic;
-               if ($this->appendSourceInfo) {
-                       // get source info
-                       if ($sourceName != null) $this->sourceName = $sourceName;
-                       else $this->sourceName = basename($this->sourceFile);
-                       list($this->sourceWidth, $this->sourceHeight, $type) = @getImageSize($this->sourceFile);
-                       $this->sourceSize = @filesize($sourceFile);
-               }
-       }
-       
-       /** 
-        * Creates a thumbnail picture (jpg/png) of a big image
-        * 
-        * @param       boolean         $rescale
-        * @return      string          thumbnail 
-        */
-       public function makeThumbnail($rescale = false) {
-               list($width, $height, $this->imageType) = @getImageSize($this->sourceFile);
-       
-               // check image size
-               if ($this->checkSize($width, $height, $rescale)) {
-                       return false;   
-               }
-
-               // try to extract the embedded thumbnail first (faster)
-               $thumbnail = false;
-               if (!$rescale && $this->useEmbedded) {
-                       $thumbnail = $this->extractEmbeddedThumbnail();
-               }
-               if (!$thumbnail) {
-                       // calculate uncompressed filesize
-                       // and cancel to avoid a memory_limit error
-                       $memoryLimit = ini_get('memory_limit');
-                       if ($memoryLimit != '') {
-                               $memoryLimit = substr($memoryLimit, 0, -1) * 1024 * 1024;
-                               $fileSize = $width * $height * ($this->imageType == 3 ? 4 : 3);
-               
-                               if (($fileSize * 2.1) + memory_get_usage() > ($memoryLimit)) {
-                                       return false;
-                               }
-                       }
-                       
-                       // calculate new picture size
-                       $x = $y = 0;
-                       if ($this->quadratic) {
-                               $newWidth = $newHeight = $this->maxWidth;
-                               if ($this->appendSourceInfo) $newHeight -= self::$sourceInfoLineHeight * 2;
-                               
-                               if ($width > $height) {
-                                       $x = ceil(($width - $height) / 2);
-                                       $width = $height;
-                               }
-                               else {
-                                       $y = ceil(($height - $width) / 2);
-                                       $height = $width;
-                               }
-                       }
-                       else {
-                               $maxHeight = $this->maxHeight;
-                               if ($this->appendSourceInfo) $maxHeight -= self::$sourceInfoLineHeight * 2;
-                               if ($this->maxWidth / $width < $maxHeight / $height) {
-                                       $newWidth = $this->maxWidth;
-                                       $newHeight = round($height * ($newWidth / $width));
-                               }
-                               else {
-                                       $newHeight = $maxHeight;        
-                                       $newWidth = round($width * ($newHeight / $height));
-                               }
-                       }
-                       
-                       // resize image
-                       $imageResource = false;
-                       
-                       // jpeg image
-                       if ($this->imageType == 2 && function_exists('imagecreatefromjpeg')) {
-                               $imageResource = @imageCreateFromJPEG($this->sourceFile);
-                       }
-                       // gif image
-                       if ($this->imageType == 1 && function_exists('imagecreatefromgif')) {
-                               $imageResource = @imageCreateFromGIF($this->sourceFile);
-                       }
-                       // png image
-                       if ($this->imageType == 3 && function_exists('imagecreatefrompng')) {
-                               $imageResource = @imageCreateFromPNG($this->sourceFile);
-                       }
-                       
-                       // could not create image
-                       if (!$imageResource) {
-                               return false;
-                       }
-                       
-                       // resize image
-                       if (function_exists('imageCreateTrueColor') && function_exists('imageCopyResampled')) {
-                               $imageNew = @imageCreateTrueColor($newWidth, $newHeight);
-                               imageAlphaBlending($imageNew, false);
-                               @imageCopyResampled($imageNew, $imageResource, 0, 0, $x, $y, $newWidth, $newHeight, $width, $height);
-                               imageSaveAlpha($imageNew, true);
-                       }
-                       else if (function_exists('imageCreate') && function_exists('imageCopyResized')) {
-                               $imageNew = @imageCreate($newWidth, $newHeight);
-                               imageAlphaBlending($imageNew, false);
-                               @imageCopyResized($imageNew, $imageResource, 0, 0, $x, $y, $newWidth, $newHeight, $width, $height);
-                               imageSaveAlpha($imageNew, true);
-                       }
-                       else return false;
-                       
-                       // create thumbnail
-                       ob_start();
-                       
-                       if ($this->imageType == 1 && function_exists('imageGIF')) {
-                               @imageGIF($imageNew);
-                               $this->mimeType = 'image/gif';
-                       }
-                       else if (($this->imageType == 1 || $this->imageType == 3) && function_exists('imagePNG')) {
-                               @imagePNG($imageNew);
-                               $this->mimeType = 'image/png';
-                       }
-                       else if (function_exists('imageJPEG')) {
-                               @imageJPEG($imageNew, '', 90);
-                               $this->mimeType = 'image/jpeg';
-                       }
-                       else {
-                               return false;
-                       }
-                       
-                       @imageDestroy($imageNew);
-                       $thumbnail = ob_get_contents();
-                       ob_end_clean();
-               }
-               
-               if ($thumbnail && $this->appendSourceInfo && !$rescale) {
-                       $thumbnail = $this->appendSourceInfo($thumbnail);
-               }
-               
-               return $thumbnail;
-       }
-       
-       /**
-        * Appends information about the source image to the thumbnail.
-        * 
-        * @param       string          $thumbnail
-        * @return      string
-        */
-       protected function appendSourceInfo($thumbnail) {
-               if (!function_exists('imageCreateFromString') || !function_exists('imageCreateTrueColor')) {
-                       return $thumbnail;
-               }
-               
-               $imageSrc = imageCreateFromString($thumbnail);
-               
-               // get image size
-               $width = imageSX($imageSrc);
-               $height = imageSY($imageSrc);
-               
-               // increase height
-               $heightDst = $height + self::$sourceInfoLineHeight * 2;
-               
-               // create new image
-               $imageDst = imageCreateTrueColor($width, $heightDst);
-               imageAlphaBlending($imageDst, false);
-               
-               // set background color
-               $background = imageColorAllocate($imageDst, 102, 102, 102);
-               imageFill($imageDst, 0, 0, $background);
-
-               // copy image
-               imageCopy($imageDst, $imageSrc, 0, 0, 0, 0, $width, $height);
-               imageSaveAlpha($imageDst, true);
-               
-               // get font size
-               $font = 2;
-               $fontWidth = imageFontWidth($font);
-               $fontHeight = imageFontHeight($font);
-               $fontColor = imageColorAllocate($imageDst, 255, 255, 255);
-               
-               // write source info
-               $line1 = $this->sourceName;
-               
-               // imageString supports only ISO-8859-1 encoded strings
-               $line1 = StringUtil::convertEncoding('UTF-8', 'ISO-8859-1', $line1);
-               
-               // truncate text if necessary
-               $maxChars = floor($width / $fontWidth);
-               if (strlen($line1) > $maxChars) {
-                       $line1 = $this->truncateSourceName($line1, $maxChars);
-               }
-               
-               $line2 = $this->sourceWidth.'x'.$this->sourceHeight.' '.FileUtil::formatFilesize($this->sourceSize);
-               
-               // write line 1
-               // calculate text position
-               $textX = 0;
-               $textY = 0;
-               
-               if ($fontHeight < self::$sourceInfoLineHeight) {
-                       $textY = intval(round((self::$sourceInfoLineHeight - $fontHeight) / 2));
-               }
-               if (strlen($line1) * $fontWidth < $width) {
-                       $textX = intval(round(($width - strlen($line1) * $fontWidth) / 2));
-               }
-               
-               imageString($imageDst, $font, $textX, $height + $textY, $line1, $fontColor);
-               
-               // write line 2
-               // calculate text position
-               $textX = 0;
-               $textY = 0;
-               
-               if ($fontHeight < self::$sourceInfoLineHeight) {
-                       $textY = self::$sourceInfoLineHeight + intval(round((self::$sourceInfoLineHeight - $fontHeight) / 2));
-               }
-               if (strlen($line2) * $fontWidth < $width) {
-                       $textX = intval(round(($width - strlen($line2) * $fontWidth) / 2));
-               }
-               
-               imageString($imageDst, $font, $textX, $height + $textY, $line2, $fontColor);
-               
-               
-               // output image
-               ob_start();
-               
-               if ($this->imageType == 1 && function_exists('imageGIF')) {
-                       @imageGIF($imageDst);
-                       $this->mimeType = 'image/gif';
-               }
-               else if (($this->imageType == 1 || $this->imageType == 3) && function_exists('imagePNG')) {
-                       @imagePNG($imageDst);
-                       $this->mimeType = 'image/png';
-               }
-               else if (function_exists('imageJPEG')) {
-                       @imageJPEG($imageDst, '', 90);
-                       $this->mimeType = 'image/jpeg';
-               }
-               else {
-                       return false;
-               }
-               
-               @imageDestroy($imageDst);
-               $thumbnail = ob_get_contents();
-               ob_end_clean();
-               
-               return $thumbnail;
-       }
-       
-       
-       /** 
-        * Extracts the embedded thumbnail picture of a jpeg or tiff image
-        * 
-        * @return      string          thumbnail 
-        */
-       protected function extractEmbeddedThumbnail() {
-               if (!function_exists('exif_thumbnail')) {
-                       return false;
-               }
-
-               $width = $height = $type = 0;
-               $thumbnail = @exif_thumbnail($this->sourceFile, $width, $height, $type);
-               if ($thumbnail && $type && $width && $height) {
-                       // resize the extracted thumbnail again if necessary
-                       // (normally the thumbnail size is set to 160px
-                       // which is recommended in EXIF >2.1 and DCF)
-                       $this->mimeType = image_type_to_mime_type($type);
-                       if (!$this->checkSize($width, $height)) {
-                               // get temporary file name
-                               $this->sourceFile = FileUtil::getTemporaryFilename('thumbnail_');
-                               
-                               // create tmp file
-                               $tmpFile = new File($this->sourceFile);
-                               $tmpFile->write($thumbnail);
-                               $tmpFile->close();
-                               unset($thumbnail, $tmpFile);
-                               
-                               // resize tmp file again
-                               return $this->makeThumbnail(true);
-                       }
-                       
-                       return $thumbnail;
-               }
-               
-               return false;
-       }
-       
-       /**
-        * Checks the size of an image.
-        */
-       protected function checkSize($width, $height, $rescale = true) {
-               $maxHeight = $this->maxHeight;
-               if ($this->appendSourceInfo && $rescale) {
-                       $maxHeight -= self::$sourceInfoLineHeight * 2;
-               }
-               
-               if ($width > $this->maxWidth || $height > $maxHeight) {
-                       return false;
-               }
-               
-               return true;
-       }
-       
-       /**
-        * Returns the mime type of the generated thumbnail.
-        * 
-        * @return      string
-        */
-       public function getMimeType() {
-               return $this->mimeType;
-       }
-       
-       /**
-        * Truncates the given file name to needed length.
-        * 
-        * @param       string          $name
-        * @param       string          $maxChars
-        * @return      string
-        */
-       protected static function truncateSourceName($name, $maxChars) {
-               $extension = '';
-               $lastPosition = strrpos($name, '.');
-               if ($lastPosition !== null) {
-                       $extension = substr($name, $lastPosition);
-                       $name = substr($name, 0, $lastPosition);
-                       $maxChars -= strlen($extension);
-               }
-               
-               return substr($name, 0, $maxChars - 3) . '...' . $extension;
-       }
-}
index 1cb165852624055472e38056a98c78a94470e634..c5de8ae30f7d6d705a45145b2569b5e4a69061ce 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 namespace wcf\system\image\adapter;
+use wcf\system\exception\SystemException;
 
 /**
  * Image adapter for bundled GD imaging library.
@@ -92,26 +93,26 @@ class GDImageAdapter implements IImageAdapter {
                $width = $height = $x = $y = 0;
                
                if ($obtainDimensions) {
-                       $widthScale = $maxWidth / $this->width;
-                       $heightScale = $maxHeight / $this->height;
-                       
-                       if ($widthScale > $heightScale) {
-                               $width = round($this->width * $heightScale, 0);
-                               $height = $maxHeight;
+                       if ($maxWidth / $this->width < $maxHeight / $this->height) {
+                               $width = $maxWidth;
+                               $height = round($this->height * ($width / $this->width));
                        }
                        else {
-                               $width = $maxWidth;
-                               $height = round($this->height * $widthScale, 0);
+                               $height = $maxHeight;
+                               $width = round($this->width * ($height / $this->height));
                        }
+                       
                }
                else {
-                       if ($this->width > $this->height) {
-                               $x = ceil(($this->width - $this->height) / 2);
-                               $width = $height = $this->height;
+                       $width = $height = $maxWidth;
+                       
+                       if ($width > $height) {
+                               $x = ceil(($width - $height) / 2);
+                               $width = $height;
                        }
                        else {
-                               $y = ceil(($this->height - $this->width) / 2);
-                               $height = $width = $this->width;
+                               $y = ceil(($height - $width) / 2);
+                               $height = $width;
                        }
                }
                
@@ -182,6 +183,10 @@ class GDImageAdapter implements IImageAdapter {
         * @see wcf\system\image\adapter\IImageAdapter::writeImage()
         */
        public function writeImage($image, $filename) {
+               if (!is_resource($image)) {
+                       throw new SystemException("Given image is not a valid image resource.");
+               }
+               
                ob_start();
                
                if ($this->type == IMAGETYPE_GIF) {
@@ -200,6 +205,20 @@ class GDImageAdapter implements IImageAdapter {
                file_put_contents($filename, $thumbnail);
        }
        
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getWidth()
+        */     
+       public function getWidth() {
+               return $this->width;
+       }
+       
+       /**
+        * @see wcf\system\image\adapter\IImageAdapter::getHeight()
+        */
+       public function getHeight() {
+               return $this->height;
+       }
+       
        /**
         * @see wcf\system\image\adapter\IImageAdapter::getImage()
         */
index d11ad04cd92f101c5f97d6c8ef886647b3a21036..99efd8c141a92ee2336d8d6d0f52b936c5e805ff 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 namespace wcf\system\image\adapter;
+use wcf\system\exception\SystemException;
 
 /**
  * Image adapter for ImageMagick imaging library.
@@ -147,6 +148,10 @@ class ImagickImageAdapter implements IImageAdapter {
         * @see wcf\system\image\adapter\IImageAdapter::writeImage()
         */
        public function writeImage($image, $filename) {
+               if (!($image instanceof \Imagick)) {
+                       throw new SystemException("Given image is not a valid Imagick-object.");
+               }
+               
                $image->writeImage($filename);
        }