rlm@3
|
1 <?php
|
rlm@3
|
2 /**
|
rlm@3
|
3 * Styx::Image - Provides an Interface to the GD-Library for image manipulation
|
rlm@3
|
4 *
|
rlm@3
|
5 * @package Styx
|
rlm@3
|
6 * @subpackage Utility
|
rlm@3
|
7 *
|
rlm@3
|
8 * @license MIT-style License
|
rlm@3
|
9 * @author Christoph Pojer <christoph.pojer@gmail.com>
|
rlm@3
|
10 *
|
rlm@3
|
11 * @link http://www.bin-co.com/php/scripts/classes/gd_image/ Based on work by "Binny V A"
|
rlm@3
|
12 */
|
rlm@3
|
13
|
rlm@3
|
14 class Image {
|
rlm@3
|
15 /**
|
rlm@3
|
16 * The path to the image file
|
rlm@3
|
17 *
|
rlm@3
|
18 * @var string
|
rlm@3
|
19 */
|
rlm@3
|
20 private $file;
|
rlm@3
|
21 /**
|
rlm@3
|
22 * The image resource
|
rlm@3
|
23 *
|
rlm@3
|
24 * @var resource
|
rlm@3
|
25 */
|
rlm@3
|
26 private $image;
|
rlm@3
|
27 /**
|
rlm@3
|
28 * Metadata regarding the image
|
rlm@3
|
29 *
|
rlm@3
|
30 * @var array
|
rlm@3
|
31 */
|
rlm@3
|
32 private $meta;
|
rlm@3
|
33
|
rlm@3
|
34 /**
|
rlm@3
|
35 * @param string $file The path to the image file
|
rlm@3
|
36 */
|
rlm@3
|
37 public function __construct($file){
|
rlm@3
|
38 $file = realpath($file);
|
rlm@3
|
39 if(!file_exists($file))
|
rlm@3
|
40 return;
|
rlm@3
|
41
|
rlm@3
|
42 $this->file = $file;
|
rlm@3
|
43 $img = getimagesize($file);
|
rlm@3
|
44
|
rlm@3
|
45 $this->meta = array(
|
rlm@3
|
46 'width' => $img[0],
|
rlm@3
|
47 'height' => $img[1],
|
rlm@3
|
48 'mime' => $img['mime'],
|
rlm@3
|
49 'ext' => end(explode('/', $img['mime'])),
|
rlm@3
|
50 );
|
rlm@3
|
51 if($this->meta['ext']=='jpg')
|
rlm@3
|
52 $this->meta['ext'] = 'jpeg';
|
rlm@3
|
53
|
rlm@3
|
54 if(!in_array($this->meta['ext'], array('gif', 'png', 'jpeg')))
|
rlm@3
|
55 return;
|
rlm@3
|
56
|
rlm@3
|
57 if(in_array($this->meta['ext'], array('gif', 'png'))){
|
rlm@3
|
58 $this->image = $this->create();
|
rlm@3
|
59
|
rlm@3
|
60 $fn = 'imagecreatefrom'.$this->meta['ext'];
|
rlm@3
|
61 $original = $fn($file);
|
rlm@3
|
62 imagecopyresampled($this->image, $original, 0, 0, 0, 0, $this->meta['width'], $this->meta['height'], $this->meta['width'], $this->meta['height']);
|
rlm@3
|
63 }else{
|
rlm@3
|
64 $this->image = imagecreatefromjpeg($file);
|
rlm@3
|
65 }
|
rlm@3
|
66 }
|
rlm@3
|
67
|
rlm@3
|
68 public function __destruct(){
|
rlm@3
|
69 if(!empty($this->image)) imagedestroy($this->image);
|
rlm@3
|
70 }
|
rlm@3
|
71
|
rlm@3
|
72 /**
|
rlm@3
|
73 * Returns the size of the image
|
rlm@3
|
74 *
|
rlm@3
|
75 * @return array
|
rlm@3
|
76 */
|
rlm@3
|
77 public function getSize(){
|
rlm@3
|
78 return array(
|
rlm@3
|
79 'width' => $this->meta['width'],
|
rlm@3
|
80 'height' => $this->meta['height'],
|
rlm@3
|
81 );
|
rlm@3
|
82 }
|
rlm@3
|
83
|
rlm@3
|
84 /**
|
rlm@3
|
85 * Creates a new, empty image with the desired size
|
rlm@3
|
86 *
|
rlm@3
|
87 * @param int $x
|
rlm@3
|
88 * @param int $y
|
rlm@3
|
89 * @param string $ext
|
rlm@3
|
90 * @return resource
|
rlm@3
|
91 */
|
rlm@3
|
92 private function create($x = null, $y = null, $ext = null){
|
rlm@3
|
93 if(!$x) $x = $this->meta['width'];
|
rlm@3
|
94 if(!$y) $y = $this->meta['height'];
|
rlm@3
|
95
|
rlm@3
|
96 $image = imagecreatetruecolor($x, $y);
|
rlm@3
|
97 if(!$ext) $ext = $this->meta['ext'];
|
rlm@3
|
98 if($ext=='png'){
|
rlm@3
|
99 imagealphablending($image, false);
|
rlm@3
|
100 imagefilledrectangle($image, 0, 0, $x, $y, imagecolorallocatealpha($image, 0, 0, 0, 127));
|
rlm@3
|
101 }
|
rlm@3
|
102
|
rlm@3
|
103 return $image;
|
rlm@3
|
104 }
|
rlm@3
|
105
|
rlm@3
|
106 /**
|
rlm@3
|
107 * Replaces the image resource with the given parameter
|
rlm@3
|
108 *
|
rlm@3
|
109 * @param resource $new
|
rlm@3
|
110 */
|
rlm@3
|
111 private function set($new){
|
rlm@3
|
112 imagedestroy($this->image);
|
rlm@3
|
113 $this->image = $new;
|
rlm@3
|
114
|
rlm@3
|
115 $this->meta['width'] = imagesx($this->image);
|
rlm@3
|
116 $this->meta['height'] = imagesy($this->image);
|
rlm@3
|
117 }
|
rlm@3
|
118
|
rlm@3
|
119 /**
|
rlm@3
|
120 * Returns the path to the image file
|
rlm@3
|
121 *
|
rlm@3
|
122 * @return string
|
rlm@3
|
123 */
|
rlm@3
|
124 public function getPathname(){
|
rlm@3
|
125 return $this->file;
|
rlm@3
|
126 }
|
rlm@3
|
127
|
rlm@3
|
128 /**
|
rlm@3
|
129 * Rotates the image by the given angle
|
rlm@3
|
130 *
|
rlm@3
|
131 * @param int $angle
|
rlm@3
|
132 * @param array $bgcolor An indexed array with red/green/blue/alpha values
|
rlm@3
|
133 * @return Image
|
rlm@3
|
134 */
|
rlm@3
|
135 public function rotate($angle, $bgcolor = null){
|
rlm@3
|
136 if(empty($this->image) || !$angle || $angle>=360) return $this;
|
rlm@3
|
137
|
rlm@3
|
138 $this->set(imagerotate($this->image, $angle, is_array($bgcolor) ? imagecolorallocatealpha($this->image, $bgcolor[0], $bgcolor[1], $bgcolor[2], !empty($bgcolor[3]) ? $bgcolor[3] : null) : $bgcolor));
|
rlm@3
|
139
|
rlm@3
|
140 return $this;
|
rlm@3
|
141 }
|
rlm@3
|
142
|
rlm@3
|
143 /**
|
rlm@3
|
144 * Resizes the image to the given size, automatically calculates
|
rlm@3
|
145 * the new ratio if parameter {@link $ratio} is set to true
|
rlm@3
|
146 *
|
rlm@3
|
147 * @param int $x
|
rlm@3
|
148 * @param int $y
|
rlm@3
|
149 * @param bool $ratio
|
rlm@3
|
150 * @return Image
|
rlm@3
|
151 */
|
rlm@3
|
152 public function resize($x = null, $y = null, $ratio = true){
|
rlm@3
|
153 if(empty($this->image) || (!$x && !$y)) return $this;
|
rlm@3
|
154
|
rlm@3
|
155 if(!$y) $y = $ratio ? $this->meta['height']*$x/$this->meta['width'] : $this->meta['height'];
|
rlm@3
|
156 if(!$x) $x = $ratio ? $this->meta['width']*$y/$this->meta['height'] : $this->meta['width'];
|
rlm@3
|
157
|
rlm@3
|
158 $new = $this->create($x, $y);
|
rlm@3
|
159 imagecopyresampled($new, $this->image, 0, 0, 0, 0, $x, $y, $this->meta['width'], $this->meta['height']);
|
rlm@3
|
160 $this->set($new);
|
rlm@3
|
161
|
rlm@3
|
162 return $this;
|
rlm@3
|
163 }
|
rlm@3
|
164
|
rlm@3
|
165 /**
|
rlm@3
|
166 * Crops the image. The values are given like margin/padding values in css
|
rlm@3
|
167 *
|
rlm@3
|
168 * <b>Example</b>
|
rlm@3
|
169 * <ul>
|
rlm@3
|
170 * <li>crop(10) - Crops by 10px on all sides</li>
|
rlm@3
|
171 * <li>crop(10, 5) - Crops by 10px on top and bottom and by 5px on left and right sides</li>
|
rlm@3
|
172 * <li>crop(10, 5, 5) - Crops by 10px on top and by 5px on left, right and bottom sides</li>
|
rlm@3
|
173 * <li>crop(10, 5, 3, 2) - Crops by 10px on top, 5px by right, 3px by bottom and 2px by left sides</li>
|
rlm@3
|
174 * </ul>
|
rlm@3
|
175 *
|
rlm@3
|
176 * @param int $top
|
rlm@3
|
177 * @param int $right
|
rlm@3
|
178 * @param int $bottom
|
rlm@3
|
179 * @param int $left
|
rlm@3
|
180 * @return Image
|
rlm@3
|
181 */
|
rlm@3
|
182 public function crop($top, $right = null, $bottom = null, $left = null){
|
rlm@3
|
183 if(empty($this->image)) return $this;
|
rlm@3
|
184
|
rlm@3
|
185 if(!is_numeric($right) && !is_numeric($bottom) && !is_numeric($left))
|
rlm@3
|
186 $right = $bottom = $left = $top;
|
rlm@3
|
187
|
rlm@3
|
188 if(!is_numeric($bottom) && !is_numeric($left)){
|
rlm@3
|
189 $bottom = $top;
|
rlm@3
|
190 $left = $right;
|
rlm@3
|
191 }
|
rlm@3
|
192
|
rlm@3
|
193 if(!is_numeric($left))
|
rlm@3
|
194 $left = $right;
|
rlm@3
|
195
|
rlm@3
|
196 $x = $this->meta['width']-$left-$right;
|
rlm@3
|
197 $y = $this->meta['height']-$top-$bottom;
|
rlm@3
|
198
|
rlm@3
|
199 if($x<0 || $y<0) return $this;
|
rlm@3
|
200
|
rlm@3
|
201 $new = $this->create($x, $y);
|
rlm@3
|
202 imagecopy($new, $this->image, 0, 0, $left, $top, $x, $y);
|
rlm@3
|
203 $this->set($new);
|
rlm@3
|
204
|
rlm@3
|
205 return $this;
|
rlm@3
|
206 }
|
rlm@3
|
207
|
rlm@3
|
208 /**
|
rlm@3
|
209 * Flips the image horizontally or vertically. To Flip both just use ->rotate(180)
|
rlm@3
|
210 *
|
rlm@3
|
211 * @see Image::rotate()
|
rlm@3
|
212 * @param string $type Either horizontal or vertical
|
rlm@3
|
213 * @return Image
|
rlm@3
|
214 */
|
rlm@3
|
215 public function flip($type){
|
rlm@3
|
216 if(empty($this->image) || !in_array($type, array('horizontal', 'vertical'))) return $this;
|
rlm@3
|
217
|
rlm@3
|
218 $new = $this->create();
|
rlm@3
|
219
|
rlm@3
|
220 if($type=='horizontal')
|
rlm@3
|
221 for($x=0;$x<$this->meta['width'];$x++)
|
rlm@3
|
222 imagecopy($new, $this->image, $this->meta['width']-$x-1, 0, $x, 0, 1, $this->meta['height']);
|
rlm@3
|
223 elseif($type=='vertical')
|
rlm@3
|
224 for($y=0;$y<$this->meta['height'];$y++)
|
rlm@3
|
225 imagecopy($new, $this->image, 0, $this->meta['height']-$y-1, 0, $y, $this->meta['width'], 1);
|
rlm@3
|
226
|
rlm@3
|
227 $this->set($new);
|
rlm@3
|
228
|
rlm@3
|
229 return $this;
|
rlm@3
|
230 }
|
rlm@3
|
231
|
rlm@3
|
232 /**
|
rlm@3
|
233 * Stores the image in the desired directory or outputs it
|
rlm@3
|
234 *
|
rlm@3
|
235 * @param string $ext
|
rlm@3
|
236 * @param string $file
|
rlm@3
|
237 */
|
rlm@3
|
238 private function process($ext = null, $file = null){
|
rlm@3
|
239 if(!$ext) $ext = $this->meta['ext'];
|
rlm@3
|
240
|
rlm@3
|
241 if($ext=='png') imagesavealpha($this->image, true);
|
rlm@3
|
242 $fn = 'image'.$ext;
|
rlm@3
|
243 $fn($this->image, $file);
|
rlm@3
|
244
|
rlm@3
|
245 // If there is a new filename change the internal name too
|
rlm@3
|
246 if($file) $this->file = $file;
|
rlm@3
|
247 }
|
rlm@3
|
248
|
rlm@3
|
249 /**
|
rlm@3
|
250 * Saves the image to the given path
|
rlm@3
|
251 *
|
rlm@3
|
252 * @param string $file Leave empty to replace the original file
|
rlm@3
|
253 * @return Image
|
rlm@3
|
254 */
|
rlm@3
|
255 public function save($file = null){
|
rlm@3
|
256 if(empty($this->image)) return $this;
|
rlm@3
|
257
|
rlm@3
|
258 if(!$file) $file = $this->file;
|
rlm@3
|
259
|
rlm@3
|
260 $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
rlm@3
|
261 if(!$ext){
|
rlm@3
|
262 $file .= '.'.$this->meta['ext'];
|
rlm@3
|
263 $ext = $this->meta['ext'];
|
rlm@3
|
264 }
|
rlm@3
|
265
|
rlm@3
|
266 if($ext=='jpg') $ext = 'jpeg';
|
rlm@3
|
267
|
rlm@3
|
268 if(!in_array($ext, array('png', 'jpeg', 'gif')))
|
rlm@3
|
269 return $this;
|
rlm@3
|
270
|
rlm@3
|
271 $this->process($ext, $file);
|
rlm@3
|
272
|
rlm@3
|
273 return $this;
|
rlm@3
|
274 }
|
rlm@3
|
275
|
rlm@3
|
276 /**
|
rlm@3
|
277 * Outputs the manipulated image
|
rlm@3
|
278 *
|
rlm@3
|
279 * @return Image
|
rlm@3
|
280 */
|
rlm@3
|
281 public function show(){
|
rlm@3
|
282 if(empty($this->image)) return $this;
|
rlm@3
|
283
|
rlm@3
|
284 header('Content-type: '.$this->meta['mime']);
|
rlm@3
|
285 $this->process();
|
rlm@3
|
286
|
rlm@3
|
287 return $this;
|
rlm@3
|
288 }
|
rlm@3
|
289
|
rlm@3
|
290 } |