├── README.md ├── composer.json ├── src └── Image │ ├── ImageProcessorInterface.php │ ├── ResizeOptions │ ├── ResizeOptionInterface.php │ ├── Extract.php │ ├── Landscape.php │ ├── Portrait.php │ ├── ResizeOptionAbstract.php │ ├── Crop.php │ └── Auto.php │ ├── GIF.php │ ├── JPEG.php │ ├── PNG.php │ └── Thumbnail.php ├── pom.xml ├── LICENSE └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | Image-Thumbnailer 2 | ================= 3 | 4 | Create thumbnail images, convert image types. 5 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zekiunal/imagethumbnailer", 3 | "description": "Create thumbnail images, convert image types", 4 | "license": "MIT License", 5 | "authors": [ 6 | { 7 | "name": "Zeki Ünal", 8 | "email": "zekiunal@gmail.com" 9 | } 10 | ], 11 | "require": {}, 12 | "autoload": { 13 | "psr-0": { 14 | "ImageThumbnailer": "src/" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Image/ImageProcessorInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name ResizeOptionInterface 10 | * @version 0.1 11 | */ 12 | interface ResizeOptionInterface 13 | { 14 | /** 15 | * @param integer $width 16 | * @param integer $height 17 | * @param integer|null $original_width 18 | * @param integer|null $original_height 19 | * @return array 20 | */ 21 | public static function getOptimalSize($width, $height, $original_width = null, $original_height = null); 22 | } 23 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | Monapi 5 | Lite 6 | Lite Image Thumbnailer 7 | 1.0 8 | pom 9 | 10 | 11 | build 12 | src 13 | tests 14 | 15 | 16 | 17 | php 18 | false 19 | true 20 | true 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Image/ResizeOptions/Extract.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name Extract 10 | * @version 0.1 11 | */ 12 | class Extract extends ResizeOptionAbstract implements ResizeOptionInterface 13 | { 14 | /** 15 | * @param integer $width 16 | * @param integer $height 17 | * @param integer $original_width 18 | * @param integer $original_height 19 | * @return array 20 | */ 21 | public static function getOptimalSize($width, $height, $original_width = null, $original_height = null) 22 | { 23 | return array('optimal_width' => $width, 'optimal_height' => $height); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Image/GIF.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image 9 | * @name GIF 10 | * @version 0.1 11 | */ 12 | class GIF implements ImageProcessorInterface 13 | { 14 | /** 15 | * @param $file_name 16 | * @return resource 17 | */ 18 | public function createImage($file_name) 19 | { 20 | return imagecreatefromgif($file_name); 21 | } 22 | 23 | /** 24 | * @param resource $image 25 | * @param string $filename [optional] 26 | * @param integer $quality [optional] 27 | * @param integer $filters [optional] 28 | * @return bool true on success or false on failure. 29 | */ 30 | public function save($image, $filename = null, $quality = null, $filters = null) 31 | { 32 | return imagegif($image, $filename); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Image/ResizeOptions/Landscape.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name Landscape 10 | * @version 0.1 11 | */ 12 | class Landscape extends ResizeOptionAbstract implements ResizeOptionInterface 13 | { 14 | /** 15 | * @param integer $width 16 | * @param integer $height 17 | * @param integer|null $original_width 18 | * @param integer|null $original_height 19 | * @return array 20 | */ 21 | public static function getOptimalSize($width, $height, $original_width = null, $original_height = null) 22 | { 23 | $optimal_height = self::getSizeByFixedWidth($width, $original_width, $original_height); 24 | return array('optimal_width' => $width, 'optimal_height' => $optimal_height); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Image/ResizeOptions/Portrait.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name Portrait 10 | * @version 0.1 11 | */ 12 | class Portrait extends ResizeOptionAbstract implements ResizeOptionInterface 13 | { 14 | 15 | /** 16 | * @param integer $width 17 | * @param integer $height 18 | * @param integer|null $original_width 19 | * @param integer|null $original_height 20 | * @return array 21 | */ 22 | public static function getOptimalSize($width, $height, $original_width = null, $original_height = null) 23 | { 24 | $optimal_width = self::getSizeByFixedHeight($height, $original_width, $original_height); 25 | return array('optimal_width' => $optimal_width, 'optimal_height' => $height); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Image/JPEG.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image 9 | * @name JPEG 10 | * @version 0.1 11 | */ 12 | class JPEG implements ImageProcessorInterface 13 | { 14 | /** 15 | * @param $file_name 16 | * @return resource 17 | */ 18 | public function createImage($file_name) 19 | { 20 | return imagecreatefromjpeg($file_name); 21 | } 22 | 23 | /** 24 | * if (imagetypes() & IMG_JPG) 25 | * 26 | * @param resource $image 27 | * @param string $filename [optional] 28 | * @param integer $quality [optional] 29 | * @param integer $filters [optional] 30 | * @return bool true on success or false on failure. 31 | */ 32 | public function save($image, $filename = null, $quality = null, $filters = null) 33 | { 34 | return imagejpeg($image, $filename, $quality); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Image/PNG.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image 9 | * @name PNG 10 | * @version 0.1 11 | */ 12 | class PNG implements ImageProcessorInterface 13 | { 14 | /** 15 | * @param $file_name 16 | * @return resource 17 | */ 18 | public function createImage($file_name) 19 | { 20 | return imagecreatefrompng($file_name); 21 | } 22 | 23 | /** 24 | * @param resource $image 25 | * @param string $filename [optional] 26 | * @param integer $quality [optional] 27 | * @param integer $filters [optional] 28 | * @return bool true on success or false on failure. 29 | */ 30 | public function save($image, $filename = null, $quality = null, $filters = null) 31 | { 32 | /** 33 | * Invert quality setting as 0 is best, not 9 34 | */ 35 | $quality = 9 - round(($quality / 100) * 9); 36 | 37 | return imagepng($image, $filename, $quality); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Image/ResizeOptions/ResizeOptionAbstract.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name ResizeOptionAbstract 10 | * @version 0.1 11 | */ 12 | abstract class ResizeOptionAbstract 13 | { 14 | /** 15 | * @param integer $height 16 | * @param integer $original_width 17 | * @param integer $original_height 18 | * @return integer 19 | */ 20 | protected static function getSizeByFixedHeight($height, $original_width, $original_height) 21 | { 22 | $ratio = $original_width / $original_height; 23 | return $height * $ratio; 24 | } 25 | 26 | /** 27 | * @param integer $width 28 | * @param integer $original_width 29 | * @param integer $original_height 30 | * @return integer 31 | */ 32 | protected static function getSizeByFixedWidth($width, $original_width, $original_height) 33 | { 34 | $ratio = $original_height / $original_width; 35 | return $width * $ratio; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Zeki ÜNAL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/Image/ResizeOptions/Crop.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name Crop 10 | * @version 0.1 11 | */ 12 | class Crop extends ResizeOptionAbstract implements ResizeOptionInterface 13 | { 14 | 15 | /** 16 | * @param integer $width 17 | * @param integer $height 18 | * @param integer|null $original_width 19 | * @param integer|null $original_height 20 | * @return array 21 | */ 22 | public static function getOptimalSize($width, $height, $original_width = null, $original_height = null) 23 | { 24 | $height_ratio = $original_height / $height; 25 | $width_ratio = $original_width / $width; 26 | 27 | if ($height_ratio < $width_ratio) { 28 | $optimal_ratio = $height_ratio; 29 | } else { 30 | $optimal_ratio = $width_ratio; 31 | } 32 | 33 | return array( 34 | 'optimal_width' => $original_width / $optimal_ratio, 35 | 'optimal_height' => $original_height / $optimal_ratio 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Image/ResizeOptions/Auto.php: -------------------------------------------------------------------------------- 1 | 6 | * @description 7 | * 8 | * @package Image\ResizeOptions 9 | * @name Auto 10 | * @version 0.1 11 | */ 12 | class Auto extends ResizeOptionAbstract implements ResizeOptionInterface 13 | { 14 | /** 15 | * @param integer $width 16 | * @param integer $height 17 | * @param integer|null $original_width 18 | * @param integer|null $original_height 19 | * @return array 20 | */ 21 | public static function getOptimalSize($width, $height, $original_width = null, $original_height = null) 22 | { 23 | return self::getSizeByAuto($width, $height, $original_width, $original_height); 24 | } 25 | 26 | protected static function getSizeByAuto($width, $height, $original_width, $original_height) 27 | { 28 | if ($original_height < $original_width) { 29 | $optimal_width = $width; 30 | $optimal_height = self::getSizeByFixedWidth($optimal_width, $original_width, $original_height); 31 | if ($optimal_height > $height) { 32 | $optimal_height = $height; 33 | $optimal_width = self::getSizeByFixedHeight($optimal_height, $original_width, $original_height); 34 | } 35 | } elseif ($original_height > $original_width) { 36 | $optimal_width = self::getSizeByFixedHeight($height, $original_width, $original_height); 37 | $optimal_height = $height; 38 | if ($optimal_width > $width) { 39 | $optimal_width = $width; 40 | $optimal_height = self::getSizeByFixedWidth($optimal_width, $original_width, $original_height); 41 | } 42 | } else { 43 | if ($height > $width) { 44 | $optimal_width = $width; 45 | $optimal_height = self::getSizeByFixedWidth($width, $original_width, $original_height); 46 | } elseif ($height < $width) { 47 | $optimal_width = self::getSizeByFixedHeight($height, $original_width, $original_height); 48 | $optimal_height = $height; 49 | } else { 50 | $optimal_width = $width; 51 | $optimal_height = $height; 52 | } 53 | } 54 | return array('optimal_width' => $optimal_width, 'optimal_height' => $optimal_height); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | 217 | .idea/ 218 | -------------------------------------------------------------------------------- /src/Image/Thumbnail.php: -------------------------------------------------------------------------------- 1 | 8 | * @description 9 | * 10 | * @package Image 11 | * @name Thumbnail 12 | * @version 0.1 13 | */ 14 | class Thumbnail 15 | { 16 | const IMAGE_JPEG = 'Image\JPEG'; 17 | 18 | const IMAGE_JPG = 'Image\JPEG'; 19 | 20 | const IMAGE_GIF = 'Image\GIF'; 21 | 22 | const IMAGE_PNG = 'Image\PNG'; 23 | 24 | /** 25 | * @var array 26 | */ 27 | protected $mime_type_class_map = array( 28 | 'image/jpeg' => Thumbnail::IMAGE_JPEG, 29 | 'image/jpg' => Thumbnail::IMAGE_JPG, 30 | 'image/gif' => Thumbnail::IMAGE_GIF, 31 | 'image/png' => Thumbnail::IMAGE_PNG 32 | ); 33 | 34 | /** 35 | * @var array 36 | */ 37 | protected $extension_class_map = array( 38 | '.jpeg' => Thumbnail::IMAGE_JPEG, 39 | '.jpg' => Thumbnail::IMAGE_JPG, 40 | '.gif' => Thumbnail::IMAGE_GIF, 41 | '.png' => Thumbnail::IMAGE_PNG 42 | ); 43 | 44 | /** 45 | * @var array 46 | */ 47 | protected $resize_option_class_map = array( 48 | 'exact' => 'Image\ResizeOptions\Exact', 49 | 'portrait' => 'Image\ResizeOptions\Portrait', 50 | 'landscape' => 'Image\ResizeOptions\Landscape', 51 | 'auto' => 'Image\ResizeOptions\Auto', 52 | 'crop' => 'Image\ResizeOptions\Crop', 53 | 'default' => 'Image\ResizeOptions\DefaultSize', 54 | ); 55 | 56 | /** 57 | * @var resource 58 | */ 59 | private $image; 60 | 61 | /** 62 | * @var integer 63 | */ 64 | private $width; 65 | 66 | /** 67 | * @var integer 68 | */ 69 | private $height; 70 | 71 | /** 72 | * @var resource 73 | */ 74 | private $image_resize; 75 | 76 | /** 77 | * @param integer $width 78 | * @param integer $height 79 | * @param string $destination 80 | */ 81 | public static function whiteImage($width, $height, $destination) 82 | { 83 | $canvas = self::createCanvas($width, $height); 84 | $bg = imagecolorallocate($canvas, 255, 255, 255); 85 | imagefilledrectangle($canvas, 0, 0, $width, $height, $bg); 86 | imagejpeg($canvas, $destination, 100); 87 | } 88 | 89 | /** 90 | * @param integer $width 91 | * @param integer $height 92 | * @return resource 93 | */ 94 | protected static function createCanvas($width, $height) 95 | { 96 | return imagecreatetruecolor($width, $height); 97 | } 98 | 99 | /** 100 | * @param string $file_name 101 | */ 102 | public function __construct($file_name) 103 | { 104 | $this->image = $this->createImage($file_name); 105 | if ($this->image === false) { 106 | $image_info = $this->getImageInfo($file_name); 107 | $processor = $this->getImageProcessorByMimeType($image_info['mime']); 108 | $this->image = $processor->createImage($file_name); 109 | $this->width = $image_info['width']; 110 | $this->height = $image_info['height']; 111 | } else { 112 | $this->width = imagesx($this->image); 113 | $this->height = imagesy($this->image); 114 | } 115 | } 116 | 117 | /** 118 | * @param string $file_name 119 | * @return array 120 | */ 121 | protected function getImageInfo($file_name) 122 | { 123 | $image = getimagesize($file_name); 124 | $info = array( 125 | 'mime' => $image['mime'], 126 | 'width' => $image[0], 127 | 'height' => $image[1] 128 | ); 129 | return $info; 130 | } 131 | 132 | /** 133 | * @param string $mime_type 134 | * @return ImageProcessorInterface 135 | */ 136 | protected function getImageProcessorByMimeType($mime_type) 137 | { 138 | return new $this->mime_type_class_map[$mime_type](); 139 | } 140 | 141 | /** 142 | * @param string $extension 143 | * @return ImageProcessorInterface 144 | */ 145 | protected function getImageProcessorByExtension($extension) 146 | { 147 | return new $this->extension_class_map[$extension](); 148 | } 149 | 150 | /** 151 | * @param string $file_name 152 | * @return resource 153 | */ 154 | protected function createImage($file_name) 155 | { 156 | $processor = $this->getImageProcessorByExtension($this->getExtension($file_name)); 157 | return $processor->createImage($file_name); 158 | } 159 | 160 | /** 161 | * @param string $file_name 162 | * @return string 163 | */ 164 | protected function getExtension($file_name) 165 | { 166 | return strtolower(strrchr($file_name, '.')); 167 | } 168 | 169 | /** 170 | * @param integer $width 171 | * @param integer $height 172 | * @param string $option 173 | * @return void 174 | */ 175 | public function resize($width, $height, $option = 'auto') 176 | { 177 | $dimensions = $this->getDimensions($width, $height, $option); 178 | $this->image_resize = self::createCanvas($dimensions['optimal_width'], $dimensions['optimal_height']); 179 | $this->reSample( 180 | $this->image_resize, 181 | $this->image, 182 | 0, 183 | 0, 184 | 0, 185 | 0, 186 | $dimensions['optimal_width'], 187 | $dimensions['optimal_height'], 188 | $this->width, 189 | $this->height 190 | ); 191 | 192 | if ($option == 'crop') { 193 | $this->crop($dimensions['optimal_width'], $dimensions['optimal_height'], $width, $height); 194 | } 195 | } 196 | 197 | /** 198 | * @param integer $width 199 | * @param integer $height 200 | * @param string $option 201 | * @return array 202 | */ 203 | private function getDimensions($width, $height, $option) 204 | { 205 | /** 206 | * @var ResizeOptionInterface $type 207 | */ 208 | $type = $this->resize_option_class_map[$option]; 209 | return $type::getOptimalSize($width, $height, $this->width, $this->height); 210 | } 211 | 212 | /** 213 | * @param integer $optimal_width 214 | * @param integer $optimal_height 215 | * @param integer $width 216 | * @param integer $height 217 | */ 218 | private function crop($optimal_width, $optimal_height, $width, $height) 219 | { 220 | $cropStartX = ($optimal_width / 2) - ($width / 2); 221 | $cropStartY = ($optimal_height / 2) - ($height / 2); 222 | $crop = $this->image_resize; 223 | $this->image_resize = self::createCanvas($width, $height); 224 | $this->reSample( 225 | $this->image_resize, 226 | $crop, 227 | 0, 228 | 0, 229 | $cropStartX, 230 | $cropStartY, 231 | $width, 232 | $height, 233 | $width, 234 | $height 235 | ); 236 | } 237 | 238 | /** 239 | * Copy and resize part of an image with re-sampling 240 | * 241 | * @param resource $dst_img 242 | * @param resource $src_img 243 | * @param integer $dst_x x-coordinate of destination point. 244 | * @param integer $dst_y y-coordinate of destination point. 245 | * @param integer $src_x x-coordinate of source point. 246 | * @param integer $src_y y-coordinate of source point. 247 | * @param integer $dst_w Destination width. 248 | * @param integer $dst_h Destination height. 249 | * @param integer $src_w Source width. 250 | * @param integer $src_h Source height. 251 | * @return bool true on success or false on failure. 252 | */ 253 | protected function reSample($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) 254 | { 255 | return imagecopyresampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); 256 | } 257 | 258 | /** 259 | * @param string $file_name 260 | * @param integer $quality 261 | */ 262 | public function save($file_name, $quality = 100) 263 | { 264 | $temp_file = tempnam(sys_get_temp_dir(), 'Tux'); 265 | $processor = $this->getImageProcessorByExtension($this->getExtension($file_name)); 266 | $processor->save($this->image_resize, $temp_file, $quality); 267 | copy($temp_file, $file_name); 268 | unlink($temp_file); 269 | imagedestroy($this->image_resize); 270 | } 271 | } 272 | --------------------------------------------------------------------------------