1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
19: class ImageSizer {
20:
21: 22: 23: 24:
25: protected $filename;
26:
27: 28: 29: 30:
31: protected $extension;
32:
33: 34: 35: 36:
37: protected $quality = 90;
38:
39: 40: 41: 42:
43: protected $image = array(
44: 'width' => 0,
45: 'height' => 0
46: );
47:
48: 49: 50: 51:
52: protected $upscaling = true;
53:
54: 55: 56: 57:
58: protected $cropping = true;
59:
60: 61: 62: 63:
64: protected $modified = false;
65:
66: 67: 68: 69:
70: protected $supportedExtensions = array(
71: 'gif',
72: 'jpg',
73: 'jpeg',
74: 'png',
75: );
76:
77: 78: 79: 80:
81: public function __construct($filename) {
82:
83: $this->filename = $filename;
84: $p = pathinfo($filename);
85: $this->extension = strtolower($p['extension']);
86: $basename = $p['basename'];
87:
88: if(!in_array($this->extension, $this->supportedExtensions))
89: throw new WireException("$basename is an unsupported image type");
90:
91: if(!$this->loadImageInfo())
92: throw new WireException("$basename is not a recogized image");
93:
94: }
95:
96: 97: 98: 99:
100: protected function setImageInfo($width, $height) {
101: $this->image['width'] = $width;
102: $this->image['height'] = $height;
103: }
104:
105: 106: 107: 108:
109: protected function loadImageInfo() {
110: if(($info = @getimagesize($this->filename)) === false) return false;
111: $this->setImageInfo($info[0], $info[1]);
112: return true;
113: }
114:
115: 116: 117: 118: 119: 120: 121: 122: 123: 124:
125: public function resize($targetWidth, $targetHeight = 0) {
126:
127:
128: if(!$this->isResizeNecessary($targetWidth, $targetHeight)) return true;
129:
130: $source = $this->filename;
131: $dest = str_replace("." . $this->extension, "_tmp." . $this->extension, $source);
132:
133: switch($this->extension) {
134: case 'gif': $image = @imagecreatefromgif($source); break;
135: case 'png': $image = @imagecreatefrompng($source); break;
136: case 'jpeg':
137: case 'jpg': $image = @imagecreatefromjpeg($source); break;
138: }
139:
140: if(!$image) return false;
141:
142: list($gdWidth, $gdHeight, $targetWidth, $targetHeight) = $this->getResizeDimensions($targetWidth, $targetHeight);
143:
144: $thumb = imagecreatetruecolor($gdWidth, $gdHeight);
145:
146: if($this->extension == 'png') {
147: imagealphablending($thumb, false);
148: imagesavealpha($thumb, true);
149: } else {
150: $bgcolor = imagecolorallocate($thumb, 0, 0, 0);
151: imagefilledrectangle($thumb, 0, 0, $gdWidth, $gdHeight, $bgcolor);
152: imagealphablending($thumb, true);
153: }
154:
155: imagecopyresampled($thumb, $image, 0, 0, 0, 0, $gdWidth, $gdHeight, $this->image['width'], $this->image['height']);
156: $thumb2 = imagecreatetruecolor($targetWidth, $targetHeight);
157:
158: if($this->extension == 'png') {
159: imagealphablending($thumb2, false);
160: imagesavealpha($thumb2, true);
161: } else {
162: $bgcolor = imagecolorallocate($thumb2, 0, 0, 0);
163: imagefilledrectangle($thumb2, 0, 0, $targetWidth, $targetHeight, 0);
164: imagealphablending($thumb2, true);
165: }
166:
167: $w1 = ($gdWidth / 2) - ($targetWidth / 2);
168: $h1 = ($gdHeight / 2) - ($targetHeight / 2);
169:
170: imagecopyresampled($thumb2, $thumb, 0, 0, $w1, $h1, $targetWidth, $targetHeight, $targetWidth, $targetHeight);
171:
172:
173: switch($this->extension) {
174: case 'gif':
175: imagegif($thumb2, $dest);
176: break;
177: case 'png':
178:
179: $quality = round(abs(($this->quality - 100) / 11.111111));
180: imagepng($thumb2, $dest, $quality);
181: break;
182: case 'jpeg':
183: case 'jpg':
184: imagejpeg($thumb2, $dest, $this->quality);
185: break;
186: }
187:
188: unlink($source);
189: rename($dest, $source);
190:
191: $this->loadImageInfo();
192: $this->modified = true;
193:
194: return true;
195: }
196:
197: 198: 199: 200:
201: public function getWidth() { return $this->image['width']; }
202:
203: 204: 205: 206:
207: public function getHeight() { return $this->image['height']; }
208:
209: 210: 211: 212:
213: protected function isResizeNecessary($targetWidth, $targetHeight) {
214:
215: $img =& $this->image;
216: $resize = true;
217:
218: if( (!$targetWidth || $img['width'] == $targetWidth) &&
219: (!$targetHeight || $img['height'] == $targetHeight)) {
220:
221: $resize = false;
222:
223: } else if(!$this->upscaling && ($targetHeight >= $img['height'] && $targetWidth >= $img['width'])) {
224:
225: $resize = false;
226: }
227:
228: return $resize;
229: }
230:
231: 232: 233: 234:
235: protected function getProportionalWidth($targetHeight) {
236: $img =& $this->image;
237: return ($targetHeight / $img['height']) * $img['width'];
238: }
239:
240: 241: 242: 243:
244: protected function getProportionalHeight($targetWidth) {
245: $img =& $this->image;
246: return ($targetWidth / $img['width']) * $img['height'];
247: }
248:
249: 250: 251: 252: 253: 254: 255: 256: 257: 258:
259: protected function getResizeDimensions($targetWidth, $targetHeight) {
260:
261: $pWidth = $targetWidth;
262: $pHeight = $targetHeight;
263:
264: $img =& $this->image;
265:
266: if(!$targetHeight) $targetHeight = floor(($targetWidth / $img['width']) * $img['height']);
267: if(!$targetWidth) $targetWidth = floor(($targetHeight / $img['height']) * $img['width']);
268:
269: $originalTargetWidth = $targetWidth;
270: $originalTargetHeight = $targetHeight;
271:
272: if($img['width'] < $img['height']) {
273: $pHeight = $this->getProportionalHeight($targetWidth);
274: } else {
275: $pWidth = $this->getProportionalWidth($targetHeight);
276: }
277:
278: if($pWidth < $targetWidth) {
279:
280: $pWidth = $targetWidth;
281: $pHeight = $this->getProportionalHeight($targetWidth);
282: }
283:
284: if($pHeight < $targetHeight) {
285:
286: $pHeight = $targetHeight;
287: $pWidth = $this->getProportionalWidth($targetHeight);
288: }
289:
290: if(!$this->upscaling) {
291:
292:
293: while($pWidth > $img['width'] || $pHeight > $img['height']) {
294:
295: if($pWidth > $img['width']) {
296: $pWidth = $img['width'];
297: $pHeight = $this->getProportionalHeight($pWidth);
298: }
299:
300: if($pHeight > $img['height']) {
301: $pHeight = $img['height'];
302: $pWidth = $this->getProportionalWidth($pHeight);
303: }
304:
305: if($targetWidth > $pWidth) $targetWidth = $pWidth;
306: if($targetHeight > $pHeight) $targetHeight = $pHeight;
307:
308: if(!$this->cropping) {
309: $targetWidth = $pWidth;
310: $targetHeight = $pHeight;
311: }
312: }
313: }
314:
315: if(!$this->cropping) {
316:
317:
318:
319:
320: if($pHeight > $originalTargetHeight) {
321: $pHeight = $originalTargetHeight;
322: $pWidth = $this->getProportionalWidth($pHeight);
323: $targetWidth = $pWidth;
324: $targetHeight = $pHeight;
325: }
326: if($pWidth > $originalTargetWidth) {
327: $pWidth = $originalTargetWidth;
328: $pHeight = $this->getProportionalHeight($pWidth);
329: $targetWidth = $pWidth;
330: $targetHeight = $pHeight;
331: }
332: }
333:
334: $r = array( 0 => (int) $pWidth,
335: 1 => (int) $pHeight,
336: 2 => (int) $targetWidth,
337: 3 => (int) $targetHeight
338: );
339:
340: return $r;
341:
342: }
343:
344: 345: 346: 347:
348: public function setUpscaling($upscaling = true) {
349: $this->upscaling = $upscaling;
350: return $this;
351: }
352:
353: 354: 355: 356:
357: public function setCropping($cropping = true) {
358: $this->cropping = $cropping;
359: return $this;
360: }
361:
362: 363: 364: 365:
366: public function isModified() {
367: return $this->modified;
368: }
369:
370: 371: 372: 373: 374: 375: 376:
377: public function setQuality($n) {
378: $this->quality = (int) $n;
379: return $this;
380: }
381:
382: }
383:
384: