Overview

Namespaces

  • None
  • PHP

Classes

  • Breadcrumb
  • Breadcrumbs
  • CacheFile
  • Comment
  • CommentArray
  • CommentFilter
  • CommentForm
  • CommentList
  • Config
  • Database
  • DatabaseQuery
  • DatabaseQuerySelect
  • DatabaseQuerySelectFulltext
  • DatabaseStopwords
  • Debug
  • Field
  • Fieldgroup
  • Fieldgroups
  • FieldgroupsArray
  • Fields
  • FieldsArray
  • Fieldtype
  • FieldtypeMulti
  • Fieldtypes
  • FileLog
  • FilenameArray
  • Fuel
  • HookEvent
  • ImageSizer
  • Inputfield
  • InputfieldsArray
  • InputfieldWrapper
  • Language
  • LanguageParser
  • Languages
  • LanguagesPageFieldValue
  • LanguageSupportInstall
  • LanguageTranslator
  • Markdown_Parser
  • MarkdownExtra_Parser
  • ModuleJS
  • ModulePlaceholder
  • Modules
  • Notice
  • NoticeError
  • NoticeMessage
  • Notices
  • NullPage
  • Page
  • PageArray
  • Pagefile
  • Pagefiles
  • PagefilesManager
  • PageFinder
  • Pageimage
  • Pageimages
  • PagerNav
  • PagerNavItem
  • Pages
  • PagesAccess
  • PagesSortfields
  • PagesType
  • Paths
  • Permission
  • Permissions
  • Process
  • ProcessController
  • ProcessWire
  • Role
  • Roles
  • Sanitizer
  • Selector
  • SelectorBitwiseAnd
  • SelectorContains
  • SelectorContainsLike
  • SelectorContainsWords
  • SelectorEnds
  • SelectorEqual
  • SelectorGreaterThan
  • SelectorGreaterThanEqual
  • SelectorLessThan
  • SelectorLessThanEqual
  • SelectorNotEqual
  • Selectors
  • SelectorStarts
  • Session
  • SessionCSRF
  • SmartyPants_Parser
  • SmartyPantsTypographer_Parser
  • SystemUpdate1
  • Template
  • TemplateFile
  • Templates
  • TemplatesArray
  • Textformatter
  • Textile
  • User
  • Users
  • Wire
  • WireArray
  • WireData
  • WireInput
  • WireInputData
  • WireSaveableItems
  • WireSaveableItemsLookup
  • WireUpload

Interfaces

  • CommentFormInterface
  • CommentListInterface
  • ConfigurableModule
  • FieldtypeLanguageInterface
  • FieldtypePageTitleCompatible
  • HasLookupItems
  • HasRoles
  • InputfieldHasArrayValue
  • Module
  • Saveable
  • TrackChanges

Exceptions

  • ProcessController404Exception
  • ProcessControllerPermissionException
  • Wire404Exception
  • WireDatabaseException
  • WireException
  • WirePermissionException

Functions

  • __
  • _n
  • _x
  • fuel
  • identify_modifier_markdown
  • Markdown
  • mdwp_add_p
  • mdwp_hide_tags
  • mdwp_show_tags
  • mdwp_strip_p
  • ProcessWireClassLoader
  • ProcessWireHostSiteConfig
  • ProcessWireShutdown
  • removeNewlines
  • SmartDashes
  • SmartEllipsis
  • SmartQuotes
  • smarty_modifier_markdown
  • smarty_modifier_smartypants
  • SmartyPants
  • tabIndent
  • unregisterGLOBALS
  • wire
  • wireDecodeJSON
  • wireEncodeJSON
  • wireMkdir
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: 
  3: /**
  4:  * ProcessWire ImageSizer
  5:  *
  6:  * ImageSizer handles resizing of a single JPG, GIF, or PNG image using GD2.
  7:  *
  8:  * ImageSizer class includes ideas adapted from comments found at PHP.net 
  9:  * in the GD functions documentation.
 10:  * 
 11:  * ProcessWire 2.x 
 12:  * Copyright (C) 2010 by Ryan Cramer 
 13:  * Licensed under GNU/GPL v2, see LICENSE.TXT
 14:  * 
 15:  * http://www.processwire.com
 16:  * http://www.ryancramer.com
 17:  *
 18:  */
 19: class ImageSizer {
 20: 
 21:     /**
 22:      * Filename to be resized 
 23:      *
 24:      */
 25:     protected $filename;
 26: 
 27:     /**
 28:      * Extension of filename
 29:      *
 30:      */
 31:     protected $extension; 
 32: 
 33:     /**
 34:      * Image quality setting, 1..100
 35:      *
 36:      */
 37:     protected $quality = 90;
 38: 
 39:     /**
 40:      * Information about the image (width/height)
 41:      *
 42:      */
 43:     protected $image = array(
 44:         'width' => 0,
 45:         'height' => 0
 46:     );
 47: 
 48:     /**
 49:      * Allow images to be upscaled / enlarged?
 50:      *
 51:      */
 52:     protected $upscaling = true;
 53: 
 54:     /**
 55:      * Allow images to be cropped to achieve necessary dimension?
 56:      *
 57:      */
 58:     protected $cropping = true;
 59: 
 60:     /**
 61:      * Was the given image modified?
 62:      *
 63:      */
 64:     protected $modified = false; 
 65: 
 66:     /**
 67:      * File extensions that are supported for resizing
 68:      *
 69:      */
 70:     protected $supportedExtensions = array(
 71:         'gif', 
 72:         'jpg', 
 73:         'jpeg', 
 74:         'png',
 75:         ); 
 76: 
 77:     /**
 78:      * Construct the ImageSizer for a single image
 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:      * Save the width and height of the image
 98:      *
 99:      */
100:     protected function setImageInfo($width, $height) {
101:         $this->image['width'] = $width;
102:         $this->image['height'] = $height; 
103:     }
104: 
105:     /**
106:      * Load the image information (width/height) using PHP's getimagesize function 
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:      * Resize the image proportionally to the given width/height
117:      *
118:      * Note: Some code used in this method is adapted from code found in comments at php.net for the GD functions
119:      *
120:      * @param int $width
121:      * @param int $height
122:      * @return bool True if the resize was successful
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') { // Adam's PNG transparency fix
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:         // write to file
173:         switch($this->extension) {
174:             case 'gif': 
175:                 imagegif($thumb2, $dest); 
176:                 break;
177:             case 'png': 
178:                 // convert 1-100 (worst-best) scale to 0-9 (best-worst) scale for PNG 
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:      * Return the image width
199:      *
200:      */
201:     public function getWidth() { return $this->image['width']; }
202: 
203:     /**
204:      * Return the image height
205:      *
206:      */
207:     public function getHeight() { return $this->image['height']; }
208: 
209:     /**
210:      * Return true if it's necessary to perform a resize with the given width/height, or false if not.
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:      * Given a target height, return the proportional width for this image
233:      *
234:      */
235:     protected function getProportionalWidth($targetHeight) {
236:         $img =& $this->image;
237:         return ($targetHeight / $img['height']) * $img['width'];
238:     }
239: 
240:     /**
241:      * Given a target width, return the proportional height for this image
242:      *
243:      */
244:     protected function getProportionalHeight($targetWidth) {
245:         $img =& $this->image;
246:         return ($targetWidth / $img['width']) * $img['height'];
247:     }
248: 
249:     /**
250:      * Get an array of the 4 dimensions necessary to perform the resize
251:      * 
252:      * Note: Some code used in this method is adapted from code found in comments at php.net for the GD functions
253:      *
254:      * Intended for use by the resize() method
255:      *
256:      * @return array
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:             // if the proportional width is smaller than specified target width 
280:             $pWidth = $targetWidth;
281:             $pHeight = $this->getProportionalHeight($targetWidth);
282:         }
283: 
284:         if($pHeight < $targetHeight) { 
285:             // if the proportional height is smaller than specified target height 
286:             $pHeight = $targetHeight;
287:             $pWidth = $this->getProportionalWidth($targetHeight); 
288:         }
289: 
290:         if(!$this->upscaling) {
291:             // we are going to shoot for something smaller than the target
292: 
293:             while($pWidth > $img['width'] || $pHeight > $img['height']) {
294:                 // favor the smallest dimension
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:             // we will make the image smaller so that none of it gets cropped
317:             // this means we'll be adjusting either the targetWidth or targetHeight 
318:             // till we have a suitable dimension 
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:      * Turn on/off upscaling
346:      *
347:      */
348:     public function setUpscaling($upscaling = true) {
349:         $this->upscaling = $upscaling; 
350:         return $this;
351:     }
352: 
353:     /**
354:      * Turn on/off cropping
355:      *
356:      */
357:     public function setCropping($cropping = true) {
358:         $this->cropping = $cropping; 
359:         return $this;
360:     }
361: 
362:     /**
363:      * Was the image modified?
364:      *  
365:      */
366:     public function isModified() {
367:         return $this->modified; 
368:     }
369: 
370:     /**
371:      * Set the image quality 1-100, where 100 is highest quality
372:      *
373:      * @param int $n
374:      * @return this
375:      *
376:      */
377:     public function setQuality($n) {
378:         $this->quality = (int) $n; 
379:         return $this;
380:     }
381: 
382: }
383: 
384: 
ProcessWire API documentation generated by ApiGen 2.6.0