PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

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

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