Overview

Packages

  • Image
  • None

Classes

  • Horde_Image
  • Horde_Image_Base
  • Horde_Image_Effect
  • Horde_Image_Effect_Border
  • Horde_Image_Effect_Gd_DropShadow
  • Horde_Image_Effect_Gd_RoundCorners
  • Horde_Image_Effect_Gd_TextWatermark
  • Horde_Image_Effect_Gd_Unsharpmask
  • Horde_Image_Effect_Im_Border
  • Horde_Image_Effect_Im_CenterCrop
  • Horde_Image_Effect_Im_Composite
  • Horde_Image_Effect_Im_DropShadow
  • Horde_Image_Effect_Im_LiquidResize
  • Horde_Image_Effect_Im_PhotoStack
  • Horde_Image_Effect_Im_PolaroidImage
  • Horde_Image_Effect_Im_RoundCorners
  • Horde_Image_Effect_Im_TextWatermark
  • Horde_Image_Effect_Im_Unsharpmask
  • Horde_Image_Effect_Imagick_Border
  • Horde_Image_Effect_Imagick_CenterCrop
  • Horde_Image_Effect_Imagick_Composite
  • Horde_Image_Effect_Imagick_DropShadow
  • Horde_Image_Effect_Imagick_LiquidResize
  • Horde_Image_Effect_Imagick_PhotoStack
  • Horde_Image_Effect_Imagick_PolaroidImage
  • Horde_Image_Effect_Imagick_RoundCorners
  • Horde_Image_Effect_Imagick_SmartCrop
  • Horde_Image_Effect_Imagick_TextWatermark
  • Horde_Image_Effect_Imagick_Unsharpmask
  • Horde_Image_Exception
  • Horde_Image_Exif
  • Horde_Image_Exif_Base
  • Horde_Image_Exif_Bundled
  • Horde_Image_Exif_Exiftool
  • Horde_Image_Exif_Parser_Base
  • Horde_Image_Exif_Php
  • Horde_Image_Gd
  • Horde_Image_Im
  • Horde_Image_Imagick
  • Horde_Image_Png
  • Horde_Image_Svg
  • Horde_Image_Swf
  • Horde_Image_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * This class defines the Horde_Image:: API, and also provides some
  4:  * utility functions, such as generating highlights of a color.
  5:  *
  6:  * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * See the enclosed file COPYING for license information (LGPL). If you
  9:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 10:  *
 11:  * @author  Chuck Hagenbuch <chuck@horde.org>
 12:  * @author  Michael J. Rubinsky <mrubinsk@horde.org>
 13:  * @package Image
 14:  */
 15: abstract class Horde_Image_Base extends EmptyIterator
 16: {
 17:     /**
 18:      * Background color.
 19:      *
 20:      * @var string
 21:      */
 22:     protected $_background = 'white';
 23: 
 24:     /**
 25:      * Observers.
 26:      *
 27:      * @var array
 28:      */
 29:     protected $_observers = array();
 30: 
 31: 
 32:     /**
 33:      * The current image data.
 34:      *
 35:      * @var string
 36:      */
 37:     protected $_data = '';
 38: 
 39:     /**
 40:      * Logger
 41:      */
 42:     protected $_logger;
 43: 
 44:     /**
 45:      * The current width of the image data.
 46:      *
 47:      * @var integer
 48:      */
 49:     protected $_width = 0;
 50: 
 51:     /**
 52:      * The current height of the image data.
 53:      *
 54:      * @var integer
 55:      */
 56:     protected $_height = 0;
 57: 
 58:     /**
 59:      * A directory for temporary files.
 60:      *
 61:      * @var string
 62:      */
 63:     protected $_tmpdir;
 64: 
 65:     /**
 66:      * Array containing available Effects
 67:      *
 68:      * @var array
 69:      */
 70:     protected $_loadedEffects = array();
 71: 
 72:     /**
 73:      * What kind of images should ImageMagick generate? Defaults to 'png'.
 74:      *
 75:      * @var string
 76:      */
 77:     protected $_type = 'png';
 78: 
 79:     /**
 80:      * Cache the context
 81:      *
 82:      * @param array
 83:      */
 84:      protected $_context;
 85: 
 86:     /**
 87:      * Constructor.
 88:      *
 89:      * @param array $params   The image object parameters. Values include:
 90:      *<pre>
 91:      *   (optional)width  - The desired image width
 92:      *   (optional)height - The desired image height
 93:      *   (optional)type   - The image type (png, jpeg etc...) If not provided,
 94:      *                      or set by the setType method, any image output will
 95:      *                      be converted to the default image type of png.
 96:      *   (optional)data   - The image binary data.
 97:      *</pre>
 98:      * @param array $context  The object context - configuration, injected objects
 99:      *<pre>
100:      *   (required)tmpdir - Temporary directory
101:      *   (optional)logger - The logger
102:      *</pre>
103:      * @throws InvalidArgumentException
104:      */
105:     protected function __construct($params, $context = array())
106:     {
107:         $this->_params = $params;
108:         $this->_context = $context;
109: 
110:         if (empty($context['tmpdir'])) {
111:             throw new InvalidArgumentException('A path to a temporary directory is required.');
112:         }
113: 
114:         $this->_tmpdir = $context['tmpdir'];
115:         if (isset($params['width'])) {
116:             $this->_width = $params['width'];
117:         }
118:         if (isset($params['height'])) {
119:             $this->_height = $params['height'];
120:         }
121:         if (!empty($params['type'])) {
122:             // We only want the extension, not the full mimetype.
123:             if (strpos($params['type'], 'image/') !== false) {
124:                 $params['type'] = substr($params['type'], 6);
125:             }
126:             $this->_type = $params['type'];
127:         }
128: 
129:         if (!empty($context['logger'])) {
130:             $this->_logger = $context['logger'];
131:         }
132: 
133:         $this->_background = isset($params['background']) ? $params['background'] : 'white';
134:     }
135: 
136:     /**
137:      * Getter for the capabilities array
138:      *
139:      * @return array
140:      */
141:     public function getCapabilities()
142:     {
143:         return $this->_capabilities;
144:     }
145: 
146:     /**
147:      * Check the existence of a particular capability.
148:      *
149:      * @param string $capability  The capability to check for.
150:      *
151:      * @return boolean
152:      */
153:     public function hasCapability($capability)
154:     {
155:         return in_array($capability, $this->_capabilities);
156:     }
157: 
158:     /**
159:      * Generate image headers.
160:      */
161:     public function headers()
162:     {
163:         header('Content-type: ' . $this->getContentType());
164:     }
165: 
166:     /**
167:      * Return the content type for this image.
168:      *
169:      * @return string  The content type for this image.
170:      */
171:     public function getContentType()
172:     {
173:         return 'image/' . $this->_type;
174:     }
175: 
176:     /**
177:      * Getter for the simplified image type.
178:      *
179:      * @return string  The type of image (png, jpg, etc...)
180:      */
181:     public function getType()
182:     {
183:         return $this->_type;
184:     }
185: 
186:     /**
187:      * Setter for the image type.
188:      *
189:      * @param string $type  The simple type for the imag (png, jpg, etc...)
190:      *
191:      * @return void
192:      */
193:     public function setType($type)
194:     {
195:         // We only want the extension, not the full mimetype.
196:         if (strpos($type, 'image/') !== false) {
197:             $type = substr($type, 6);
198:         }
199:         $old = $this->_type;
200:         $this->_type = $type;
201: 
202:         return $old;
203:     }
204: 
205:     /**
206:      * Draw a shaped point at the specified (x,y) point. Useful for
207:      * scatter diagrams, debug points, etc. Draws squares, circles,
208:      * diamonds, and triangles.
209:      *
210:      * @param integer $x     The x coordinate of the point to brush.
211:      * @param integer $y     The y coordinate of the point to brush.
212:      * @param string $color  The color to brush the point with.
213:      * @param string $shape  What brush to use? Defaults to a square.
214:      */
215:     public function brush($x, $y, $color = 'black', $shape = 'square')
216:     {
217:         switch ($shape) {
218:         case 'triangle':
219:             $verts[0] = array('x' => $x + 3, 'y' => $y + 3);
220:             $verts[1] = array('x' => $x, 'y' => $y - 3);
221:             $verts[2] = array('x' => $x - 3, 'y' => $y + 3);
222:             $this->polygon($verts, $color, $color);
223:             break;
224: 
225:         case 'circle':
226:             $this->circle($x, $y, 3, $color, $color);
227:             break;
228: 
229:         case 'diamond':
230:             $verts[0] = array('x' => $x - 3, 'y' => $y);
231:             $verts[1] = array('x' => $x, 'y' => $y + 3);
232:             $verts[2] = array('x' => $x + 3, 'y' => $y);
233:             $verts[3] = array('x' => $x, 'y' => $y - 3);
234:             $this->polygon($verts, $color, $color);
235:             break;
236: 
237:         case 'square':
238:         default:
239:             $this->rectangle($x - 2, $y - 2, 4, 4, $color, $color);
240:             break;
241:         }
242:     }
243: 
244:     /**
245:      * Reset the image data to defaults.
246:      */
247:     public function reset()
248:     {
249:         $this->_data = '';
250:         $this->_width = null;
251:         $this->_height = null;
252:         $this->_background = 'white';
253:     }
254: 
255:     /**
256:      * Get the height and width of the current image data.
257:      *
258:      * @return array  An hash with 'width' containing the width,
259:      *                'height' containing the height of the image.
260:      */
261:     public function getDimensions()
262:     {
263:         // Check if we know it already
264:         if ($this->_width == 0 && $this->_height == 0) {
265:             $tmp = $this->toFile();
266:             $details = @getimagesize($tmp);
267:             list($this->_width, $this->_height) = $details;
268:             unlink($tmp);
269:         }
270: 
271:         return array('width' => $this->_width,
272:                      'height' => $this->_height);
273:     }
274: 
275:     /**
276:      * Load the image data from a string.
277:      *
278:      * @param string $id          An arbitrary id for the image.
279:      * @param string $image_data  The data to use for the image.
280:      */
281:     public function loadString($image_data)
282:     {
283:         $this->reset();
284:         $this->_data = $image_data;
285:     }
286: 
287:     /**
288:      * Load the image data from a file.
289:      *
290:      * @param string $filename  The full path and filename to the file to load
291:      *                          the image data from. The filename will also be
292:      *                          used for the image id.
293:      *
294:      * @return mixed  True if successful or already loaded, PEAR Error if file
295:      *                does not exist or could not be loaded.
296:      * @throws Horde_Image_Exception
297:      */
298:     public function loadFile($filename)
299:     {
300:         $this->reset();
301:         if (!file_exists($filename)) {
302:             throw new Horde_Image_Exception(sprintf("The image file, %s, does not exist.", $filename));
303:         }
304:         if (!$this->_data = file_get_contents($filename)) {
305:             throw new Horde_Image_Exception(sprintf("Could not load the image file %s", $filename));
306:         }
307: 
308:         return true;
309:     }
310: 
311:     /**
312:      * Ouputs image data to file.  If $data is false, outputs current
313:      * image data after performing any pending operations on the data.
314:      * If $data contains raw image data, outputs that data to file without
315:      * regard for $this->_data
316:      *
317:      * @param mixed  String of binary image data | false
318:      *
319:      * @return string  Path to temporary file.
320:      */
321:     public function toFile($data = false)
322:     {
323:         $tmp = Horde_Util::getTempFile('img', false, $this->_tmpdir);
324:         $fp = @fopen($tmp, 'wb');
325:         fwrite($fp, $data ? $data : $this->raw());
326:         fclose($fp);
327:         return $tmp;
328:     }
329: 
330:     /**
331:      * Display the current image.
332:      */
333:     public function display()
334:     {
335:         $this->headers();
336:         echo $this->raw(true);
337:     }
338: 
339:     /**
340:      * Returns the raw data for this image.
341:      *
342:      * @param boolean $convert  If true, the image data will be returned in the
343:      *                          target format, independently from any image
344:      *                          operations.
345:      *
346:      * @return string  The raw image data.
347:      */
348:     public function raw($convert = false)
349:     {
350:         return $this->_data;
351:     }
352: 
353:     /**
354:      * Attempts to apply requested effect to this image.
355:      *
356:      * @param string $type    The type of effect to apply.
357:      * @param array $params   Any parameters for the effect.
358:      *
359:      * @return boolean
360:      */
361:     public function addEffect($type, $params)
362:     {
363:         $class = str_replace('Horde_Image_', '', get_class($this));
364:         $params['logger'] = $this->_logger;
365:         $effect = Horde_Image_Effect::factory($type, $class, $params);
366:         $effect->setImageObject($this);
367:         return $effect->apply();
368:     }
369: 
370:     /**
371:      * Load a list of available effects for this driver.
372:      */
373:     public function getLoadedEffects()
374:     {
375:         if (!count($this->_loadedEffects)) {
376:             $class = str_replace('Horde_Image_', '', get_class($this));
377:             $this->_loadedEffects = array();
378:             // First, load the driver-agnostic Effects.
379:             $path = dirname(__FILE__) . '/Effect/';
380:             if (is_dir($path)) {
381:                 if ($handle = opendir($path)) {
382:                     while (($file = readdir($handle)) !== false) {
383:                         if (substr($file, -4, 4) == '.php') {
384:                             $this->_loadedEffects[] = substr($file, 0, strlen($file) - 4);
385:                         }
386:                     }
387:                 }
388:             }
389: 
390:             // Driver specific effects.
391:             $path = $path . $class;
392:             if (is_dir($path)) {
393:                 if ($handle = opendir($path)) {
394:                     while (($file = readdir($handle)) !== false) {
395:                         if (substr($file, -4, 4) == '.php') {
396:                             $this->_loadedEffects[] = substr($file, 0, strlen($file) - 4);
397:                         }
398:                     }
399:                 }
400:             }
401:         }
402: 
403:         return $this->_loadedEffects;
404:     }
405: 
406:     /**
407:      * Apply any effects in the effect queue.
408:      */
409:     public function applyEffects()
410:     {
411:         $this->raw();
412:     }
413: 
414:     public function getTmpDir()
415:     {
416:         return $this->_tmpdir;
417:     }
418: 
419:     /**
420:      * Utility function to zero out cached geometry information. Shouldn't
421:      * really be called from client code, but is needed since Effects may need
422:      * to clear these.
423:      *
424:      */
425:     public function clearGeometry()
426:     {
427:         $this->_height = 0;
428:         $this->_width = 0;
429:     }
430: 
431:     protected function _logDebug($message)
432:     {
433:         if (!empty($this->_logger)) {
434:             $this->_logger->debug($message);
435:         }
436:     }
437: 
438:     protected function _logErr($message)
439:     {
440:         if (!empty($this->_logger)) {
441:             $this->_logger->err($message);
442:         }
443:     }
444: 
445:     /**
446:      * Request a specific image from the collection of images.
447:      *
448:      * @param integer $index  The index to return
449:      *
450:      * @return Horde_Image_Base
451:      */
452:     abstract function getImageAtIndex($index);
453: 
454:     /**
455:      * Return the number of image pages available in the image object.
456:      *
457:      * @return integer
458:      */
459:     abstract function getImagePageCount();
460: 
461: }
462: 
API documentation generated by ApiGen