PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/saf/lib/Ext/Pitlib/Driver.php

https://github.com/lux/sitellite
PHP | 789 lines | 297 code | 113 blank | 379 comment | 27 complexity | 3620edce110314dd8c2bcf0fdbca682f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, GPL-3.0
  1. <?php
  2. // vim: tabstop=4: expandtab: sts=4: ai: sw=4:
  3. /**
  4. * @author Charles Brunet <cbrunet@php.net>
  5. * @author Kaloyan K. Tsvetkov <kaloyan@kaloyan.info>
  6. * @license http://opensource.org/licenses/lgpl-license.php
  7. * GNU Lesser General public License Version 2.1
  8. * @package Pitlib
  9. * @subpackage Pitlib.Driver
  10. * @version $Id: class.driver.php 17 2007-12-05 11:57:55Z Mrasnika $
  11. */
  12. /////////////////////////////////////////////////////////////////////////////
  13. /**
  14. * Pitlib abstract driver
  15. *
  16. * @package Pitlib
  17. * @subpackage Pitlib.Driver
  18. * @abstract
  19. */
  20. abstract Class Pitlib_Driver {
  21. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  22. /**
  23. * Maps to supported image types
  24. * @var array
  25. * @access protected
  26. */
  27. protected $__read = array();
  28. protected $__write = array();
  29. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  30. /**
  31. * Checks whether the environment is compatible with this driver
  32. *
  33. * @return boolean
  34. * @access public
  35. * @abstract
  36. */
  37. abstract public function is_compatible();
  38. /**
  39. * Return the driver name
  40. *
  41. * @return string
  42. * @access public
  43. * @abstract
  44. */
  45. abstract public function name ();
  46. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  47. /**
  48. * Resize an image
  49. *
  50. * @param Pitlib_Tmp $tmp
  51. * @param integer $width
  52. * @param integer $height
  53. * @param mixed $mode
  54. * @return boolean
  55. * @access public
  56. */
  57. public function resize (Pitlib_Tmp $tmp, $width, $height, $mode) {
  58. // no params ?
  59. //
  60. if (!$width && !$height) {
  61. throw new Pitlib_Exception (
  62. sprintf(
  63. 'Neither width nor height provided '
  64. . ' for resizing operation '
  65. . ' of "%s" ',
  66. $tmp->source_filename
  67. )
  68. );
  69. }
  70. // resize by only one parameter ?
  71. //
  72. if (!$width || !$height) {
  73. $mode = Pitlib::RESIZE_PROPORTIONAL;
  74. if (!$width) {
  75. $width = floor(
  76. $tmp->image_width * $height / $tmp->image_height
  77. );
  78. }
  79. if (!$height) {
  80. $height = floor(
  81. $tmp->image_height * $width / $tmp->image_width
  82. );
  83. }
  84. }
  85. // stretch or proportional
  86. //
  87. switch ($mode) {
  88. case Pitlib::RESIZE_STRETCH:
  89. $p_width = $width;
  90. $p_height = $height;
  91. break;
  92. case Pitlib::RESIZE_FIT:
  93. if (($tmp->image_height <= $height) &&
  94. ($tmp->image_width <= $width)) {
  95. $p_width = $tmp->image_width;
  96. $p_height = $tmp->image_height;
  97. // break the switch\case
  98. //
  99. break;
  100. }
  101. // if indeed has to be resized, fall
  102. // back to the proportional resize
  103. //
  104. ;
  105. default:
  106. case Pitlib::RESIZE_PROPORTIONAL:
  107. $p1_width = $width;
  108. $p1_height = round(
  109. $tmp->image_height * $width / $tmp->image_width
  110. );
  111. if ($p1_height - $height > 1) {
  112. $p_height = $height;
  113. $p_width = round(
  114. $tmp->image_width * $height / $tmp->image_height
  115. );
  116. } else {
  117. $p_width = $p1_width;
  118. $p_height = $p1_height;
  119. }
  120. break;
  121. }
  122. // do the resize
  123. //
  124. $r = $this->__resize($tmp, $p_width, $p_height);
  125. // new dimensions ?
  126. //
  127. $tmp->image_width = $p_width;
  128. $tmp->image_height = $p_height;
  129. return $r;
  130. }
  131. /**
  132. * Convert an image from one file-type to another
  133. *
  134. * @param Pitlib_Tmp $tmp
  135. * @param mixed $type Image type or Mime type
  136. * @return boolean
  137. * @access public
  138. */
  139. public function convert(Pitlib_Tmp $tmp, $type) {
  140. if (strpos ('/', $type)) {
  141. $type = Pitlib_Type::from_mime ($type);
  142. }
  143. // supported format ? (for writing)
  144. //
  145. if (!$this->supported($type, Pitlib::SUPPORT_WRITE)) {
  146. throw new Pitlib_Exception(
  147. sprintf(
  148. 'Requested conversion format "%s" is not supported',
  149. $type
  150. )
  151. );
  152. }
  153. $tmp->save = $type;
  154. return true;
  155. }
  156. /**
  157. * Watermark an image
  158. *
  159. * @param Pitlib_Tmp $tmp
  160. * @param string $watermark_image
  161. * @param mixed $position
  162. * @param mixed $scalable
  163. * @param float $scalable_factor
  164. * @return boolean
  165. * @access public
  166. */
  167. public function watermark(Pitlib_Tmp $tmp, $watermark_image, $position,
  168. $scalable, $scalable_factor) {
  169. // open
  170. //
  171. $wi = new Pitlib_Image($watermark_image);
  172. $wt = $this->prepare($wi);
  173. // dimensions
  174. //
  175. $target_width = $tmp->image_width;
  176. $target_height = $tmp->image_height;
  177. $watermark_width =& $wt->image_width;
  178. $watermark_height =& $wt->image_height;
  179. // watermark scalable ?
  180. //
  181. if ((Pitlib::WATERMARK_SCALABLE_ENABLED == $scalable)
  182. && ($watermark_width > $target_width * $scalable_factor
  183. || $watermark_height > $target_height * $scalable_factor)
  184. ){
  185. // jump thru tha loop
  186. //
  187. $t2 = $this->__tmpimage($wt->source);
  188. if ($this->resize($t2,
  189. intval($target_width * $scalable_factor),
  190. intval($target_height * $scalable_factor),
  191. Pitlib::RESIZE_PROPORTIONAL)
  192. ){
  193. unlink($t2->source_filename);
  194. @unlink ($t2->source_filename.'.alpha'); //ugly, but I don't know where to erase it...
  195. $this->__destroy_target($wt);
  196. // new watermark created, destroy old
  197. //
  198. $this->__destroy_source($wt);
  199. // copy new watermark
  200. //
  201. $wt->source = $t2->target;
  202. $this->__destroy_source($t2);
  203. // ^
  204. // DO NOT UNSET $t2->target!!!
  205. // adjust watermark dimensions
  206. //
  207. $watermark_width = $t2->image_width;
  208. $watermark_height =$t2->image_height;
  209. }
  210. }
  211. else {
  212. $this->__destroy_target ($wt);
  213. }
  214. // position
  215. //
  216. switch ($position) {
  217. // tile watermark
  218. //
  219. case Pitlib::WATERMARK_TILE :
  220. $watermark_x = 1;
  221. $watermark_y = 1;
  222. // create tile
  223. //
  224. for ($x = 0; $x < ceil($target_width / $watermark_width);
  225. $x++) {
  226. for ($y = 0; $y < ceil($target_height / $watermark_height);
  227. $y++) {
  228. // skip the first one
  229. //
  230. if (!$x && !$y) continue;
  231. // copy the watermark
  232. //
  233. $this->__copy($tmp, $wt,
  234. $watermark_x + $x*$watermark_width,
  235. $watermark_y + $y*$watermark_height
  236. );
  237. }
  238. }
  239. break;
  240. // top left, north west
  241. //
  242. case Pitlib::WATERMARK_TOP_LEFT :
  243. $watermark_x = 1;
  244. $watermark_y = 1;
  245. break;
  246. // top center, north
  247. //
  248. case Pitlib::WATERMARK_TOP_CENTER :
  249. $watermark_x = ($target_width - $watermark_width)/2;
  250. $watermark_y = 1;
  251. break;
  252. // top right, north east
  253. //
  254. case Pitlib::WATERMARK_TOP_RIGHT :
  255. $watermark_x = $target_width - $watermark_width ;
  256. $watermark_y = 1;
  257. break;
  258. // middle left, west
  259. //
  260. case Pitlib::WATERMARK_MIDDLE_LEFT :
  261. $watermark_x = 1;
  262. $watermark_y = ($target_height - $watermark_height)/2;
  263. break;
  264. // middle center, center
  265. //
  266. case Pitlib::WATERMARK_MIDDLE_CENTER :
  267. $watermark_x = ($target_width - $watermark_width)/2;
  268. $watermark_y = ($target_height - $watermark_height)/2;
  269. break;
  270. // middle right, east
  271. //
  272. case Pitlib::WATERMARK_MIDDLE_RIGHT :
  273. $watermark_x = $target_width - $watermark_width ;
  274. $watermark_y = ($target_height - $watermark_height)/2;
  275. break;
  276. // bottom left, south west
  277. //
  278. case Pitlib::WATERMARK_BOTTOM_LEFT :
  279. $watermark_x = 1;
  280. $watermark_y = $target_height - $watermark_height ;
  281. break;
  282. // bottom center, south
  283. //
  284. case Pitlib::WATERMARK_BOTTOM_CENTER :
  285. $watermark_x = ($target_width - $watermark_width)/2;
  286. $watermark_y = $target_height - $watermark_height ;
  287. break;
  288. default :
  289. // bottom right, south east
  290. //
  291. case Pitlib::WATERMARK_BOTTOM_RIGHT :
  292. $watermark_x = $target_width - $watermark_width ;
  293. $watermark_y = $target_height - $watermark_height ;
  294. break;
  295. }
  296. // copy the watermark
  297. //
  298. $this->__copy($tmp, $wt, $watermark_x, $watermark_y);
  299. // destroy watermark image
  300. //
  301. $this->__destroy_source($wt);
  302. return true;
  303. }
  304. /**
  305. * Make the image greyscale
  306. *
  307. * @param Pitlib_Tmp $tmp
  308. * @return boolean
  309. * @access public
  310. */
  311. public function grayscale(Pitlib_Tmp $tmp) {
  312. return $this->__grayscale($tmp);
  313. }
  314. /**
  315. * Rotate the image clockwise
  316. *
  317. * @param Pitlib_Tmp $tmp
  318. * @param float $angle
  319. * @param Pitlib_Color $color
  320. * @return boolean
  321. * @access public
  322. */
  323. public function rotate(Pitlib_Tmp $tmp, $angle, Pitlib_Color $color=null) {
  324. // color ?
  325. //
  326. if (!isset($color)) {
  327. $color = new Pitlib_Color;
  328. $color->set(255, 255, 255);
  329. }
  330. return $this->__rotate($tmp, $angle, $color);
  331. }
  332. /**
  333. * Resize an image by "framing" it with the provided width and height
  334. *
  335. * @param Pitlib_Tmp $tmp
  336. * @param integer $width
  337. * @param integer $height
  338. * @param Pitlib_Color $color
  339. * @return boolean
  340. * @access public
  341. */
  342. public function frame(Pitlib_Tmp $tmp, $width, $height,
  343. Pitlib_Color $color=null) {
  344. // color ?
  345. //
  346. if (!isset($color)) {
  347. $color = new Pitlib_Color;
  348. $color->set(255, 255, 255);
  349. }
  350. // resize it
  351. //
  352. $this->resize($tmp, $width, $height, Pitlib::RESIZE_FIT);
  353. // get canvas
  354. //
  355. $t2 = $this->__canvas($width, $height, $color);
  356. // target
  357. //
  358. $t3 = new Pitlib_Tmp;
  359. $t3->source =& $tmp->target;
  360. $t3->image_width = $tmp->image_width;
  361. $t3->image_height = $tmp->image_height;
  362. // apply the image
  363. //
  364. $this->__copy(
  365. $t2, $t3,
  366. round(($t2->image_width - $t3->image_width)/2),
  367. round(($t2->image_height - $t3->image_height)/2)
  368. );
  369. // cook the result
  370. //
  371. $this->__destroy_target($tmp);
  372. $tmp->target = $t2->target;
  373. $tmp->image_width = $t2->image_width;
  374. $tmp->image_height = $t2->image_height;
  375. return true;
  376. }
  377. /**
  378. * Copy applied_image onto the current image
  379. *
  380. * @param Pitlib_Tmp $tmp
  381. * @param string $applied_image filepath to the image that is going to be
  382. * copied
  383. * @param integer $x
  384. * @param integer $y
  385. * @return boolean
  386. * @access public
  387. */
  388. public function copy(Pitlib_Tmp $tmp, $applied_image, $x, $y) {
  389. // open
  390. //
  391. $ci = new Pitlib_Image ($applied_image);
  392. $ct = $this->prepare($ci);
  393. $this->__copy($tmp, $ct, $x, $y);
  394. $this->__destroy_source($ct);
  395. $this->__destroy_target($ct);
  396. return true;
  397. }
  398. /**
  399. * Crop the image
  400. *
  401. * @param Pitlib_Tmp $tmp
  402. * @param integer $x
  403. * @param integer $y
  404. * @param integer $width
  405. * @param integer $height
  406. * @return boolean
  407. * @access public
  408. */
  409. public function crop(Pitlib_Tmp $tmp, $x, $y, $width, $height) {
  410. return $this->__crop($tmp, $x, $y, $width, $height);
  411. }
  412. /**
  413. * Vertically mirror (flip) the image
  414. *
  415. * @param Pitlib_Tmp $tmp
  416. * @return boolean
  417. * @access public
  418. */
  419. public function flip(Pitlib_Tmp $tmp) {
  420. return $this->__flip($tmp);
  421. }
  422. /**
  423. * Horizontally mirror (flop) the image
  424. *
  425. * @param Pitlib_Tmp $tmp
  426. * @return boolean
  427. * @access public
  428. */
  429. public function flop(Pitlib_Tmp $tmp) {
  430. return $this->__flop($tmp);
  431. }
  432. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  433. /**
  434. * Prepare an image for processing it
  435. *
  436. * @param Pitlib_Image $image
  437. * @return Pitlib_Tmp
  438. * @access public
  439. */
  440. public function prepare(Pitlib_Image $image) {
  441. // create new temporary object
  442. //
  443. $tmp = new Pitlib_Tmp;
  444. $tmp->source_filename = $image->source();
  445. $tmp->target_filename = $image->target();
  446. $tmp->quality = $image->get_quality();
  447. // failed opening ?
  448. //
  449. if (!$this->__open($tmp)) {
  450. print_r ($tmp);
  451. throw new Pitlib_Exception (
  452. 'Unable to open source image'
  453. );
  454. }
  455. return $tmp;
  456. }
  457. /**
  458. * Save an image after being processed
  459. *
  460. * @param Pitlib_Tmp $tmp
  461. * @return boolean
  462. * @access public
  463. */
  464. public function save(Pitlib_Tmp $tmp) {
  465. return $this->__write($tmp);
  466. }
  467. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  468. /**
  469. * Copy one image to another
  470. *
  471. * @param Pitlib_Tmp $tmp_target
  472. * @param Pitlib_Tmp $tmp_source
  473. * @param integer $destination_x
  474. * @param integer $destination_y
  475. * @return boolean
  476. * @access protected
  477. * @abstract
  478. */
  479. protected function __copy(Pitlib_Tmp $tmp_target,
  480. Pitlib_Tmp $tmp_source, $destination_x, $destination_y) {
  481. throw new Pitlib_Exception_OperationNotSupported;
  482. }
  483. /**
  484. * Do the actual resize of an image
  485. *
  486. * @param Pitlib_Tmp $tmp
  487. * @param integer $width
  488. * @param integer $height
  489. * @return boolean
  490. * @access protected
  491. * @abstract
  492. */
  493. protected function __resize(Pitlib_Tmp $tmp, $width, $height) {
  494. throw new Pitlib_Exception_OperationNotSupported;
  495. }
  496. /**
  497. * Make the image greyscale
  498. *
  499. * @param Pitlib_Tmp $tmp
  500. * @return boolean
  501. * @access protected
  502. * @abstract
  503. */
  504. protected function __grayscale(Pitlib_Tmp $tmp) {
  505. throw new Pitlib_Exception_OperationNotSupported;
  506. }
  507. /**
  508. * Rotate the image clockwise
  509. *
  510. * @param Pitlib_Tmp $tmp
  511. * @param float $angle
  512. * @param Pitlib_Color $color
  513. * @return boolean
  514. * @access protected
  515. * @abstract
  516. */
  517. protected function __rotate(Pitlib_Tmp $tmp, $angle,
  518. Pitlib_Color $color) {
  519. throw new Pitlib_Exception_OperationNotSupported;
  520. }
  521. /**
  522. * Get canvas
  523. *
  524. * @param integer $width
  525. * @param integer $height
  526. * @param Pitlib_Color $color
  527. * @return Pitlib_Tmp
  528. * @access protected
  529. * @abstract
  530. */
  531. protected function __canvas($width, $height, Pitlib_Color $color) {
  532. throw new Pitlib_Exception_OperationNotSupported;
  533. }
  534. /**
  535. * Crop the image
  536. *
  537. * @param Pitlib_Tmp $tmp
  538. * @param integer $x
  539. * @param integer $y
  540. * @param integer $width
  541. * @param integer $height
  542. * @return boolean
  543. * @access protected
  544. * @abstract
  545. */
  546. protected function __crop(Pitlib_Tmp $tmp, $x, $y,
  547. $width, $height) {
  548. throw new Pitlib_Exception_OperationNotSupported;
  549. }
  550. /**
  551. * Vertically mirror (flip) the image
  552. *
  553. * @param Pitlib_Tmp $tmp
  554. * @return boolean
  555. * @access protected
  556. * @abstract
  557. */
  558. protected function __flip(Pitlib_Tmp $tmp) {
  559. throw new Pitlib_Exception_OperationNotSupported;
  560. }
  561. /**
  562. * Horizontally mirror (flop) the image
  563. *
  564. * @param Pitlib_Tmp $tmp
  565. * @return boolean
  566. * @access protected
  567. * @abstract
  568. */
  569. protected function __flop(Pitlib_Tmp $tmp) {
  570. throw new Pitlib_Exception_OperationNotSupported;
  571. }
  572. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  573. /**
  574. * Get supported mime-types
  575. *
  576. * @param mixed $mode
  577. * @return array
  578. * @access public
  579. */
  580. public function get_supported_types($mode) {
  581. switch ($mode) {
  582. case 'Pitlib::SUPPORT_READ':
  583. return array_values($this->__read);
  584. break;
  585. case 'Pitlib::SUPPORT_WRITE':
  586. return array_values($this->__write);
  587. break;
  588. default :
  589. case 'Pitlib::SUPPORT_READ_WRITE' :
  590. return array_unique(
  591. array_intersect(
  592. array_values($this->__write),
  593. array_values($this->__read)
  594. )
  595. );
  596. break;
  597. }
  598. }
  599. /**
  600. * Returnes whether an image format is supported or not
  601. *
  602. * @param string $type
  603. * @param integer $mode
  604. * @return boolean
  605. * @access public
  606. */
  607. public function supported($type, $mode) {
  608. return in_array(
  609. $type,
  610. $this->get_supported_types($mode)
  611. );
  612. }
  613. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  614. /**
  615. * Open the source and target image for processing it
  616. *
  617. * @param Pitlib_Tmp $tmp
  618. * @return boolean
  619. * @access protected
  620. * @abstract
  621. */
  622. abstract protected function __open(Pitlib_Tmp $tmp);
  623. /**
  624. * Write the image after being processed
  625. *
  626. * @param Pitlib_Tmp $tmp
  627. * @return boolean
  628. * @access protected
  629. * @abstract
  630. */
  631. abstract protected function __write(Pitlib_Tmp $tmp);
  632. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  633. /**
  634. * Return a name for a temporary file
  635. * @return string
  636. * @access protected
  637. */
  638. protected function __tmpfile() {
  639. return tempnam(Pitlib::$TEMPDIR, 'pitlib_');
  640. }
  641. /**
  642. * Generate a temporary object for the provided argument
  643. *
  644. * @param mixed $handler
  645. * @param string $filename the filename will be automatically generated
  646. * on the fly, but if you want you can use the filename provided by
  647. * this argument
  648. * @return Pitlib_Tmp
  649. * @access protected
  650. * @abstract
  651. */
  652. abstract protected function __tmpimage($handler, $filename=null);
  653. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  654. /**
  655. * Destroy the source for the provided temporary object
  656. *
  657. * @param Pitlib_Tmp $tmp
  658. * @return boolean
  659. * @access protected
  660. * @abstract
  661. */
  662. abstract protected function __destroy_source(Pitlib_Tmp $tmp);
  663. /**
  664. * Destroy the target for the provided temporary object
  665. *
  666. * @param Pitlib_Tmp $tmp
  667. * @return boolean
  668. * @access protected
  669. * @abstract
  670. */
  671. abstract protected function __destroy_target(Pitlib_Tmp $tmp);
  672. // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  673. //--end-of-class--
  674. }
  675. /////////////////////////////////////////////////////////////////////////////
  676. ?>