PageRenderTime 282ms CodeModel.GetById 254ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/fuel/core/classes/image/driver.php

https://bitbucket.org/sriedel/iccrm-wip
PHP | 869 lines | 561 code | 60 blank | 248 comment | 73 complexity | ab77fdc4e63cbaaac44575dfd7e56e84 MD5 | raw file
  1<?php
  2
  3/**
  4 * Part of the Fuel framework.
  5 *
  6 * Image manipulation class.
  7 *
  8 * @package		Fuel
  9 * @version		1.0
 10 * @license		MIT License
 11 * @copyright	2010 - 2011 Fuel Development Team
 12 * @link		http://fuelphp.com
 13 */
 14
 15namespace Fuel\Core;
 16
 17abstract class Image_Driver
 18{
 19
 20	protected $image_fullpath  = null;
 21	protected $image_directory = null;
 22	protected $image_filename  = null;
 23	protected $image_extension = null;
 24	protected $new_extension   = null;
 25	protected $config          = array();
 26	protected $queued_actions  = array();
 27	protected $accepted_extensions;
 28
 29	public function __construct($config)
 30	{
 31		\Config::load('image', true);
 32		if (is_array($config))
 33		{
 34			$this->config = array_merge(\Config::get('image'), $config);
 35		}
 36		else
 37		{
 38			$this->config = \Config::get('image');
 39		}
 40		$this->debug("Image Class was initialized using the " . $this->config['driver'] . " driver.");
 41	}
 42	/**
 43	 * Accepts configuration in either an array (as $index) or a pairing using $index and $value
 44	 *
 45	 * @param   string  $index  The index to be set, or an array of configuration options.
 46	 * @param   mixed   $value  The value to be set if $index is not an array.
 47	 * @return  Image_Driver
 48	 */
 49	public function config($index = null, $value = null)
 50	{
 51		if (is_array($index))
 52		{
 53			if (isset($index['driver']))
 54			{
 55				throw new \RuntimeException("The driver cannot be changed after initialization!");
 56			}
 57			$this->config = array_merge($this->config, $index);
 58		}
 59		elseif ($index != null)
 60		{
 61			if ($index == 'driver')
 62			{
 63				throw new \RuntimeException("The driver cannot be changed after initialization!");
 64			}
 65			$this->config[$index] = $value;
 66		}
 67
 68		return $this;
 69	}
 70
 71	/**
 72	 * Exectues the presets set in the config. Additional parameters replace the $1, $2, ect.
 73	 *
 74	 * @param   string  $name  The name of the preset.
 75	 * @return  Image_Driver
 76	 */
 77	public function preset($name)
 78	{
 79		$vars = func_get_args();
 80		if (isset($this->config['presets'][$name]))
 81		{
 82			$old_config   = $this->config;
 83			$this->config = array_merge($this->config, $this->config['presets'][$name]);
 84			foreach ($this->config['actions'] AS $action)
 85			{
 86				$func = $action[0];
 87				array_shift($action);
 88				for ($i = 0; $i < count($action); $i++)
 89				{
 90					for ($x = count($vars) - 1; $x >= 0; $x--)
 91					{
 92						$action[$i] = preg_replace('#\$' . $x . '#', $vars[$x], $action[$i]);
 93					}
 94				}
 95				call_user_func_array(array($this, $func), $action);
 96			}
 97			$this->config = $old_config;
 98		}
 99		else
100		{
101			throw new \InvalidArgumentException("Could not load preset $name, you sure it exists?");
102		}
103		return $this;
104	}
105
106	/**
107	 * Loads the image and checks if its compatible.
108	 *
109	 * @param   string  $filename								The file to load
110	 * @param   string  $return_data						Decides if it should return the images data, or just "$this".
111	 * @param   mixed   $force_extension				Decides if it should force the extension witht this (or false)
112	 * @return  Image_Driver
113	 */
114	public function load($filename, $return_data = false, $force_extension = false)
115	{
116		// First check if the filename exists
117		$filename = realpath($filename);
118		$return = array(
119			'filename'    => $filename,
120			'return_data' => $return_data
121		);
122		if (file_exists($filename))
123		{
124			// Check the extension
125			$ext = $this->check_extension($filename, false, $force_extension);
126			if ($ext !== false)
127			{
128				$return = array_merge($return, array(
129					'image_fullpath'  => $filename,
130					'image_directory' => dirname($filename),
131					'image_filename'  => basename($filename),
132					'image_extension' => $ext
133				));
134				if ( ! $return_data)
135				{
136					$this->image_fullpath = $filename;
137					$this->image_directory = dirname($filename);
138					$this->image_filename = basename($filename);
139					$this->image_extension = $ext;
140				}
141			}
142			else
143			{
144				throw new \RuntimeException("The library does not support this filetype for $filename.");
145			}
146		}
147		else
148		{
149			throw new \OutOfBoundsException("Image file $filename does not exist.");
150		}
151		return $return;
152	}
153
154	/**
155	 * Crops the image using coordinates or percentages.
156	 *
157	 * Positive whole numbers or percentages are coordinates from the top left.
158	 *
159	 * Negative whole numbers or percentages are coordinates from the bottom right.
160	 *
161	 * @param   integer  $x1  X-Coordinate for first set.
162	 * @param   integer  $y1  Y-Coordinate for first set.
163	 * @param   integer  $x2  X-Coordinate for second set.
164	 * @param   integer  $y2  Y-Coordinate for second set.
165	 * @return  Image_Driver
166	 */
167	public function crop($x1, $y1, $x2, $y2)
168	{
169		$this->queue('crop', $x1, $y1, $x2, $y2);
170		return $this;
171	}
172
173	/**
174	 * Executes the crop event when the queue is ran.
175	 *
176	 * Formats the crop method input for use with driver specific methods
177	 *
178	 * @param   integer  $x1  X-Coordinate for first set.
179	 * @param   integer  $y1  Y-Coordinate for first set.
180	 * @param   integer  $x2  X-Coordinate for second set.
181	 * @param   integer  $y2  Y-Coordinate for second set.
182	 * @return  array    An array of variables for the specific driver.
183	 */
184	protected function _crop($x1, $y1, $x2, $y2)
185	{
186		$y1 === null and $y1 = $x1;
187		$x2 === null and $x2 = "-" . $x1;
188		$y2 === null and $y2 = "-" . $y1;
189
190		$x1 = $this->convert_number($x1, true);
191		$y1 = $this->convert_number($y1, false);
192		$x2 = $this->convert_number($x2, true);
193		$y2 = $this->convert_number($y2, false);
194
195		return array(
196			'x1' => $x1,
197			'y1' => $y1,
198			'x2' => $x2,
199			'y2' => $y2
200		);
201	}
202
203	/**
204	 * Resizes the image. If the width or height is null, it will resize retaining the original aspect ratio.
205	 *
206	 * @param   integer  $width   The new width of the image.
207	 * @param   integer  $height  The new height of the image.
208	 * @param   boolean  $keepar  If false, allows stretching of the image.
209	 * @param   boolean  $pad     Adds padding to the image when resizing.
210	 * @return  Image_Driver
211	 */
212	public function resize($width, $height = null, $keepar = true, $pad = false)
213	{
214		$this->queue('resize', $width, $height, $keepar, $pad);
215		return $this;
216	}
217
218	/**
219	 * Executes the resize event when the queue is ran.
220	 *
221	 * Formats the resize method input for use with driver specific methods.
222	 *
223	 * @param   integer  $width   The new width of the image.
224	 * @param   integer  $height  The new height of the image.
225	 * @param   boolean  $keepar  If false, allows stretching of the image.
226	 * @param   boolean  $pad     Adds padding to the image when resizing.
227	 * @return  array    An array of variables for the specific driver.
228	 */
229	protected function _resize($width, $height = null, $keepar = true, $pad = true)
230	{
231		if ($height == null or $width == null)
232		{
233			if ($height == null and substr($width, -1) == '%')
234			{
235				$height = $width;
236			}
237			elseif (substr($height, -1) == '%' and $width == null)
238			{
239				$width = $height;
240			}
241			else
242			{
243				$sizes = $this->sizes();
244				if ($height == null and $width != null)
245				{
246					$height = $width * ($sizes->height / $sizes->width);
247				}
248				elseif ($height != null and $width == null)
249				{
250					$width = $height * ($sizes->width / $sizes->height);
251				}
252				else
253				{
254					throw new \InvalidArgumentException("Width and height cannot be null.");
255				}
256			}
257		}
258
259		$origwidth  = $this->convert_number($width, true);
260		$origheight = $this->convert_number($height, false);
261		$width      = $origwidth;
262		$height     = $origheight;
263		$sizes      = $this->sizes();
264		$x = 0;
265		$y = 0;
266		if ($keepar)
267		{
268			// See which is the biggest ratio
269			if (function_exists('bcdiv'))
270			{
271				$width_ratio  = bcdiv((float) $width, $sizes->width, 10);
272				$height_ratio = bcdiv((float) $height, $sizes->height, 10);
273				$compare = bccomp($width_ratio, $height_ratio, 10);
274				if ($compare > -1)
275				{
276					$height = ceil((float) bcmul($sizes->height, $height_ratio, 10));
277					$width = ceil((float) bcmul($sizes->width, $height_ratio, 10));
278				}
279				else
280				{
281					$height = ceil((float) bcmul($sizes->height, $width_ratio, 10));
282					$width = ceil((float) bcmul($sizes->width, $width_ratio, 10));
283				}
284			}
285			else
286			{
287				$width_ratio  = $width / $sizes->width;
288				$height_ratio = $height / $sizes->height;
289				if ($width_ratio >= $height_ratio)
290				{
291					$height = ceil($sizes->height * $height_ratio);
292					$width = ceil($sizes->width * $height_ratio);
293				}
294				else
295				{
296					$height = ceil($sizes->height * $width_ratio);
297					$width = ceil($sizes->width * $width_ratio);
298				}
299			}
300		}
301
302		if ($pad)
303		{
304			$x = floor(($origwidth - $width) / 2);
305			$y = floor(($origheight - $height) / 2);
306		}
307		else
308		{
309			$origwidth  = $width;
310			$origheight = $height;
311		}
312
313		return array(
314			'width'   => $width,
315			'height'  => $height,
316			'cwidth'  => $origwidth,
317			'cheight' => $origheight,
318			'x' => $x,
319			'y' => $y
320		);
321	}
322
323	public function crop_resize($width, $height = null)
324	{
325		is_null($height) and $height = $width;
326		$this->queue('crop_resize', $width, $height);
327		return $this;
328	}
329
330	protected function _crop_resize($width, $height)
331	{
332		// Determine the crop size
333		$sizes   = $this->sizes();
334		$width   = $this->convert_number($width, true);
335		$height  = $this->convert_number($height, false);
336
337		if (function_exists('bcdiv'))
338		{
339			if (bccomp(bcdiv($sizes->width, $width, 10), bcdiv($sizes->height, $height, 10), 10) < 1)
340			{
341				$this->_resize($width, 0, true, false);
342			}
343			else
344			{
345				$this->_resize(0, $height, true, false);
346			}
347		}
348		else
349		{
350			if ($sizes->width / $width < $sizes->height / $height)
351			{
352				$this->_resize($width, 0, true, false);
353			}
354			else
355			{
356				$this->_resize(0, $height, true, false);
357			}
358		}
359
360		$sizes = $this->sizes();
361		$y = floor(max(0, $sizes->height - $height) / 2);
362		$x = floor(max(0, $sizes->width - $width) / 2);
363		$this->_crop($x, $y, $x + $width, $y + $height);
364	}
365
366	/**
367	 * Rotates the image
368	 *
369	 * @param   integer  $degrees  The degrees to rotate, negatives integers allowed.
370	 * @return  Image_Driver
371	 */
372	public function rotate($degrees)
373	{
374		$this->queue('rotate', $degrees);
375		return $this;
376	}
377
378	/**
379	 * Executes the rotate event when the queue is ran.
380	 *
381	 * Formats the rotate method input for use with driver specific methods
382	 *
383	 * @param   integer  $degrees  The degrees to rotate, negatives integers allowed.
384	 * @return  array    An array of variables for the specific driver.
385	 */
386	protected function _rotate($degrees)
387	{
388		$degrees %= 360;
389		if ($degrees < 0)
390		{
391			$degrees = 360 + $degrees;
392		}
393		return array(
394			'degrees' => $degrees
395		);
396	}
397
398	/**
399	 * Adds a watermark to the image.
400	 *
401	 * @param   string   $filename  The filename of the watermark file to use.
402	 * @param   string   $position  The position of the watermark, ex: "bottom right", "center center", "top left"
403	 * @param   integer  $padding   The amount of padding (in pixels) from the position.
404	 * @return  Image_Driver
405	 */
406	public function watermark($filename, $position, $padding = 5)
407	{
408		$this->queue('watermark', $filename, $position, $padding);
409		return $this;
410	}
411
412	/**
413	 * Executes the watermark event when the queue is ran.
414	 *
415	 * Formats the watermark method input for use with driver specific methods
416	 *
417	 * @param   string   $filename  The filename of the watermark file to use.
418	 * @param   string   $position  The position of the watermark, ex: "bottom right", "center center", "top left"
419	 * @param   integer  $padding   The amount of padding (in pixels) from the position.
420	 * @return  array    An array of variables for the specific driver.
421	 */
422	protected function _watermark($filename, $position, $padding = 5)
423	{
424		$filename = realpath($filename);
425		$return = false;
426		if (file_exists($filename) and $this->check_extension($filename, false))
427		{
428			$x = 0;
429			$y = 0;
430			$wsizes = $this->sizes($filename);
431			$sizes  = $this->sizes();
432			// Get the x and y  positions.
433			list($ypos, $xpos) = explode(' ', $position);
434			switch ($xpos)
435			{
436				case 'left':
437					$x = $padding;
438				break;
439				case 'middle':
440				case 'center':
441					$x = ($sizes->width / 2) - ($wsizes->width / 2);
442				break;
443				case 'right':
444					$x = $sizes->width - $wsizes->width - $padding;
445				break;
446			}
447			switch ($ypos)
448			{
449				case 'top':
450					$y = $padding;
451				break;
452				case 'middle':
453				case 'center':
454					$y = ($sizes->height / 2) - ($wsizes->height / 2);
455				break;
456				case 'bottom':
457					$y = $sizes->height - $wsizes->height - $padding;
458				break;
459			}
460			$this->debug("Watermark being placed at $x,$y");
461			$return = array(
462				'filename' => $filename,
463				'x' => $x,
464				'y' => $y,
465				'padding' => $padding
466			);
467		}
468		return $return;
469	}
470
471	/**
472	 * Adds a border to the image.
473	 *
474	 * @param   integer  $size   The side of the border, in pixels.
475	 * @param   string   $color  A hexadecimal color.
476	 * @return  Image_Driver
477	 */
478	public function border($size, $color = null)
479	{
480		$this->queue('border', $size, $color);
481		return $this;
482	}
483
484	/**
485	 * Executes the border event when the queue is ran.
486	 *
487	 * Formats the border method input for use with driver specific methods
488	 *
489	 * @param   integer  $size   The side of the border, in pixels.
490	 * @param   string   $color  A hexadecimal color.
491	 * @return  array    An array of variables for the specific driver.
492	 */
493	protected function _border($size, $color = null)
494	{
495		empty($color) and $color = $this->config['bgcolor'];
496
497		return array(
498			'size' => $size,
499			'color' => $color
500		);
501	}
502
503	/**
504	 * Masks the image using the alpha channel of the image input.
505	 *
506	 * @param   string  $maskimage  The location of the image to use as the mask
507	 * @return  Image_Driver
508	 */
509	public function mask($maskimage)
510	{
511		$this->queue('mask', $maskimage);
512		return $this;
513	}
514
515	/**
516	 * Executes the mask event when the queue is ran.
517	 *
518	 * Formats the mask method input for use with driver specific methods
519	 *
520	 * @param   string  $maskimage  The location of the image to use as the mask
521	 * @return  array   An array of variables for the specific driver.
522	 */
523	protected function _mask($maskimage)
524	{
525		return array(
526			'maskimage' => $maskimage
527		);
528	}
529
530	/**
531	 * Adds rounded corners to the image.
532	 *
533	 * @param   integer  $radius
534	 * @param   integer  $sides      Accepts any combination of "tl tr bl br" separated by spaces, or null for all sides
535	 * @param   integer  $antialias  Sets the antialias range.
536	 * @return  Image_Driver
537	 */
538	public function rounded($radius, $sides = null, $antialias = null)
539	{
540		$this->queue('rounded', $radius, $sides, $antialias);
541		return $this;
542	}
543
544	/**
545	 * Executes the rounded event when the queue is ran.
546	 *
547	 * Formats the rounded method input for use with driver specific methods
548	 *
549	 * @param   integer  $radius
550	 * @param   integer  $sides      Accepts any combination of "tl tr bl br" separated by spaces, or null for all sides
551	 * @param   integer  $antialias  Sets the antialias range.
552	 * @return  array    An array of variables for the specific driver.
553	 */
554	protected function _rounded($radius, $sides, $antialias)
555	{
556		$radius < 0 and $radius = 0;
557		$tl = $tr = $bl = $br = $sides == null;
558
559		if ($sides != null)
560		{
561			$sides = explode(' ', $sides);
562			foreach ($sides as $side)
563			{
564				if ($side == 'tl' or $side == 'tr' or $side == 'bl' or $side == 'br')
565				{
566					$$side = true;
567				}
568			}
569		}
570		$antialias == null and $antialias = 1;
571
572		return array(
573			'radius' => $radius,
574			'tl' => $tl,
575			'tr' => $tr,
576			'bl' => $bl,
577			'br' => $br,
578			'antialias' => $antialias
579		);
580	}
581
582	/**
583	 * Turns the image into a grayscale version
584	 *
585	 * @return  Image_Driver
586	 */
587	public function grayscale()
588	{
589		$this->queue('grayscale');
590		return $this;
591	}
592
593	/**
594	 * Executes the grayscale event when the queue is ran.
595	 */
596	abstract protected function _grayscale();
597
598	/**
599	 * Saves the image, and optionally attempts to set permissions
600	 *
601	 * @param   string  $filename     The location where to save the image.
602	 * @param   string  $permissions  Allows unix style permissions
603	 * @return  array
604	 */
605	public function save($filename, $permissions = null)
606	{
607		$directory = dirname($filename);
608		if ( ! is_dir($directory))
609		{
610			throw new \OutOfBoundsException("Could not find directory \"$directory\"");
611		}
612
613		if ( ! $this->check_extension($filename, true))
614		{
615			$filename .= "." . $this->image_extension;
616		}
617		// Touch the file
618		if ( ! touch($filename))
619		{
620			throw new \RuntimeException("Do not have permission to write to \"$filename\"");
621		}
622
623		// Set the new permissions
624		if ($permissions != null and ! chmod($filename, $permissions))
625		{
626			throw new \RuntimeException("Could not set permissions on the file.");
627		}
628
629		$this->debug("", "Saving image as <code>$filename</code>");
630		return array(
631			'filename' => $filename
632		);
633	}
634
635	/**
636	 * Saves the file in the original location, adding the append and prepend to the filename.
637	 *
638	 * @param   string   $append       The string to append to the filename
639	 * @param   string   $prepend      The string to prepend to the filename
640	 * @param   string   $extension    The extension to save the image as, null defaults to the loaded images extension.
641	 * @param   integer  $permissions  The permissions to attempt to set on the file.
642	 * @return  Image_Driver
643	 */
644	public function save_pa($append, $prepend = null, $extension = null, $permissions = null)
645	{
646		$filename = substr($this->image_filename, 0, -(strlen($this->image_extension) + 1));
647		$fullpath = $this->image_directory.'/'.$append.$filename.$prepend.'.'.
648			($extension !== null ? $extension : $this->image_extension);
649		$this->save($fullpath, $permissions);
650		return $this;
651	}
652
653	/**
654	 * Outputs the file directly to the user.
655	 *
656	 * @param   string  $filetype  The extension type to use. Ex: png, jpg, gif
657	 * @return  array
658	 */
659	public function output($filetype = null)
660	{
661		if ($filetype == null)
662		{
663			$filetype = $this->config['filetype'] == null ? $this->image_extension : $this->config['filetype'];
664		}
665
666		if ($this->check_extension($filetype, false))
667		{
668			if ( ! $this->config['debug'])
669			{
670				$mimetype = $filetype === 'jpg' ? 'jpeg' : $filetype;
671				header('Content-Type: image/' . $mimetype);
672			}
673			$this->new_extension = $filetype;
674		}
675		else
676		{
677			throw new \FuelException("Image extension $filetype is unsupported.");
678		}
679
680		$this->debug('', "Outputting image as $filetype");
681		return array(
682			'filetype' => $filetype
683		);
684	}
685
686	/**
687	 * Returns sizes for the currently loaded image, or the image given in the $filename.
688	 *
689	 * @param   string  $filename  The location of the file to get sizes for.
690	 * @return  object  An object containing width and height variables.
691	 */
692	abstract public function sizes($filename = null);
693
694	/**
695	 * Adds a background to the image using the 'bgcolor' config option.
696	 */
697	abstract protected function add_background();
698
699	/**
700	 * Creates a new color usable by all drivers.
701	 *
702	 * @param   string   $hex    The hex code of the color
703	 * @return  array    rgba representation of the hex and alpha values.
704	 */
705	protected function create_hex_color($hex)
706	{
707		if ($hex == null)
708		{
709			$red = 0;
710			$green = 0;
711			$blue = 0;
712		}
713		else
714		{
715			// Check if theres a # in front
716			if (substr($hex, 0, 1) == '#')
717			{
718				$hex = substr($hex, 1);
719			}
720
721			// Break apart the hex
722			if (strlen($hex) == 6)
723			{
724				$red   = hexdec(substr($hex, 0, 2));
725				$green = hexdec(substr($hex, 2, 2));
726				$blue  = hexdec(substr($hex, 4, 2));
727			}
728			else
729			{
730				$red   = hexdec(substr($hex, 0, 1).substr($hex, 0, 1));
731				$green = hexdec(substr($hex, 1, 1).substr($hex, 1, 1));
732				$blue  = hexdec(substr($hex, 2, 1).substr($hex, 2, 1));
733			}
734		}
735
736		return array(
737			'red' => $red,
738			'green' => $green,
739			'blue' => $blue,
740		);
741	}
742
743	/**
744	 * Checks if the extension is accepted by this library, and if its valid sets the $this->image_extension variable.
745	 *
746	 * @param   string   $filename
747	 * @param   boolean  $writevar					Decides if the extension should be written to $this->image_extension
748	 * @param   mixed		 $force_extension		Decides if the extension should be overridden with this (or false)
749	 * @return  boolean
750	 */
751	protected function check_extension($filename, $writevar = true, $force_extension = false)
752	{
753		$return = false;
754
755		if ($force_extension !== false and in_array($force_extension, $this->accepted_extensions))
756		{
757			return $force_extension;
758		}
759
760		foreach ($this->accepted_extensions as $ext)
761		{
762			if (strtolower(substr($filename, strlen($ext) * -1)) == strtolower($ext))
763			{
764				$writevar and $this->image_extension = $ext;
765				$return = $ext;
766			}
767		}
768		return $return;
769	}
770
771	/**
772	 * Converts percentages, negatives, and other values to absolute integers.
773	 *
774	 * @param   string   $input
775	 * @param   boolean  $x  Determines if the number relates to the x-axis or y-axis.
776	 * @return  integer  The converted number, usable with the image being edited.
777	 */
778	protected function convert_number($input, $x = null)
779	{
780		// Sanitize double negatives
781		$input = str_replace('--', '', $input);
782
783		$orig = $input;
784		$sizes = $this->sizes();
785		$size = $x ? $sizes->width : $sizes->height;
786		// Convert percentages to absolutes
787		if (substr($input, -1) == '%')
788		{
789			$input = floor((substr($input, 0, -1) / 100) * $size);
790		}
791		// Negatives are based off the bottom right
792		if ($x !== null and $input < 0)
793		{
794			$input = $size + $input;
795		}
796		return $input;
797	}
798
799	/**
800	 * Queues a function to run at a later time.
801	 *
802	 * @param  string  $function  The name of the function to be ran, without the leading _
803	 */
804	protected function queue($function)
805	{
806		$func = func_get_args();
807		$tmpfunc = array();
808		for ($i = 0; $i < count($func); $i++)
809		{
810			$tmpfunc[$i] = var_export($func[$i], true);
811		}
812
813		$this->debug("Queued <code>" . implode(", ", $tmpfunc) . "</code>");
814		$this->queued_actions[] = $func;
815	}
816
817	/**
818	 * Runs all queued actions on the loaded image.
819	 *
820	 * @param  boolean  $clear  Decides if the queue should be cleared once completed.
821	 */
822	public function run_queue($clear = null)
823	{
824		foreach ($this->queued_actions as $action)
825		{
826			$tmpfunc = array();
827			for ($i = 0; $i < count($action); $i++)
828			{
829				$tmpfunc[$i] = var_export($action[$i], true);
830			}
831			$this->debug('', "<b>Executing <code>" . implode(", ", $tmpfunc) . "</code></b>");
832			call_user_func_array(array(&$this, '_' . $action[0]), array_slice($action, 1));
833		}
834		if (($clear === null and $this->config['clear_queue']) or $clear === true)
835		{
836			$this->queued_actions = array();
837		}
838	}
839
840	/**
841	 * Reloads the image.
842	 *
843	 * @return  Image_Driver
844	 */
845	public function reload()
846	{
847		$this->debug("Reloading was called!");
848		$this->load($this->image_fullpath, false, $this->image_extension);
849		return $this;
850	}
851
852	/**
853	 * Used for debugging image output.
854	 *
855	 * @param  string  $message
856	 */
857	protected function debug()
858	{
859		if ($this->config['debug'])
860		{
861			$messages = func_get_args();
862			foreach ($messages as $message)
863			{
864				echo '<div>' . $message . '&nbsp;</div>';
865			}
866		}
867	}
868}
869