PageRenderTime 77ms CodeModel.GetById 23ms RepoModel.GetById 5ms app.codeStats 0ms

/filemanager/include/php_image_magician.php

https://github.com/molnarzoli82/viola
PHP | 3320 lines | 1624 code | 614 blank | 1082 comment | 289 complexity | 873b98d1cd68064b004ce98c73b40ab4 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0
  1. <?php
  2. # ========================================================================#
  3. #
  4. # This work is licensed under the Creative Commons Attribution 3.0 Unported
  5. # License. To view a copy of this license,
  6. # visit http://creativecommons.org/licenses/by/3.0/ or send a letter to
  7. # Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
  8. # 94041, USA.
  9. #
  10. # All rights reserved.
  11. #
  12. # Author: Jarrod Oberto
  13. # Version: 1.5.1
  14. # Date: 10-05-11
  15. # Purpose: Provide tools for image manipulation using GD
  16. # Param In: See functions.
  17. # Param Out: Produces a resized image
  18. # Requires : Requires PHP GD library.
  19. # Usage Example:
  20. # include("lib/php_image_magician.php");
  21. # $magicianObj = new resize('images/car.jpg');
  22. # $magicianObj -> resizeImage(150, 100, 0);
  23. # $magicianObj -> saveImage('images/car_small.jpg', 100);
  24. #
  25. # - See end of doc for more examples -
  26. #
  27. # Supported file types include: jpg, png, gif, bmp, psd (read)
  28. #
  29. #
  30. #
  31. # The following functions are taken from phpThumb() [available from
  32. # http://phpthumb.sourceforge.net], and are used with written permission
  33. # from James Heinrich.
  34. # - GD2BMPstring
  35. # - GetPixelColor
  36. # - LittleEndian2String
  37. #
  38. # The following functions are from Marc Hibbins and are used with written
  39. # permission (are also under the Attribution-ShareAlike
  40. # [http://creativecommons.org/licenses/by-sa/3.0/] license.
  41. # -
  42. #
  43. # PhpPsdReader is used with written permission from Tim de Koning.
  44. # [http://www.kingsquare.nl/phppsdreader]
  45. #
  46. #
  47. #
  48. # Modificatoin history
  49. # Date Initials Ver Description
  50. # 10-05-11 J.C.O 0.0 Initial build
  51. # 01-06-11 J.C.O 0.1.1 * Added reflections
  52. # * Added Rounded corners
  53. # * You can now use PNG interlacing
  54. # * Added shadow
  55. # * Added caption box
  56. # * Added vintage filter
  57. # * Added dynamic image resizing (resize on the fly)
  58. # * minor bug fixes
  59. # 05-06-11 J.C.O 0.1.1.1 * Fixed undefined variables
  60. # 17-06-11 J.C.O 0.1.2 * Added image_batch_class.php class
  61. # * Minor bug fixes
  62. # 26-07-11 J.C.O 0.1.4 * Added support for external images
  63. # * Can now set the crop poisition
  64. # 03-08-11 J.C.O 0.1.5 * Added reset() method to reset resource to
  65. # original input file.
  66. # * Added method addTextToCaptionBox() to
  67. # simplify adding text to a caption box.
  68. # * Added experimental writeIPTC. (not finished)
  69. # * Added experimental readIPTC. (not finished)
  70. # 11-08-11 J.C.O * Added initial border presets.
  71. # 30-08-11 J.C.O * Added 'auto' crop option to crop portrait
  72. # images near the top.
  73. # 08-09-11 J.C.O * Added cropImage() method to allow standalone
  74. # cropping.
  75. # 17-09-11 J.C.O * Added setCropFromTop() set method - set the
  76. # percentage to crop from the top when using
  77. # crop 'auto' option.
  78. # * Added setTransparency() set method - allows you
  79. # to turn transparency off (like when saving
  80. # as a jpg).
  81. # * Added setFillColor() set method - set the
  82. # background color to use instead of transparency.
  83. # 05-11-11 J.C.O 0.1.5.1 * Fixed interlacing option
  84. # 0-07-12 J.C.O 1.0
  85. #
  86. # Known issues & Limitations:
  87. # -------------------------------
  88. # Not so much an issue, the image is destroyed on the deconstruct rather than
  89. # when we have finished with it. The reason for this is that we don't know
  90. # when we're finished with it as you can both save the image and display
  91. # it directly to the screen (imagedestroy($this->imageResized))
  92. #
  93. # Opening BMP files is slow. A test with 884 bmp files processed in a loop
  94. # takes forever - over 5 min. This test inlcuded opening the file, then
  95. # getting and displaying its width and height.
  96. #
  97. # $forceStretch:
  98. # -------------------------------
  99. # On by default.
  100. # $forceStretch can be disabled by calling method setForceStretch with false
  101. # parameter. If disabled, if an images original size is smaller than the size
  102. # specified by the user, the original size will be used. This is useful when
  103. # dealing with small images.
  104. #
  105. # If enabled, images smaller than the size specified will be stretched to
  106. # that size.
  107. #
  108. # Tips:
  109. # -------------------------------
  110. # * If you're resizing a transparent png and saving it as a jpg, set
  111. # $keepTransparency to false with: $magicianObj->setTransparency(false);
  112. #
  113. # FEATURES:
  114. # * EASY TO USE
  115. # * BMP SUPPORT (read & write)
  116. # * PSD (photoshop) support (read)
  117. # * RESIZE IMAGES
  118. # - Preserve transparency (png, gif)
  119. # - Apply sharpening (jpg) (requires PHP >= 5.1.0)
  120. # - Set image quality (jpg, png)
  121. # - Resize modes:
  122. # - exact size
  123. # - resize by width (auto height)
  124. # - resize by height (auto width)
  125. # - auto (automatically determine the best of the above modes to use)
  126. # - crop - resize as best as it can then crop the rest
  127. # - Force stretching of smaller images (upscale)
  128. # * APPLY FILTERS
  129. # - Convert to grey scale
  130. # - Convert to black and white
  131. # - Convert to sepia
  132. # - Convert to negative
  133. # * ROTATE IMAGES
  134. # - Rotate using predefined "left", "right", or "180"; or any custom degree amount
  135. # * EXTRACT EXIF DATA (requires exif module)
  136. # - make
  137. # - model
  138. # - date
  139. # - exposure
  140. # - aperture
  141. # - f-stop
  142. # - iso
  143. # - focal length
  144. # - exposure program
  145. # - metering mode
  146. # - flash status
  147. # - creator
  148. # - copyright
  149. # * ADD WATERMARK
  150. # - Specify exact x, y placement
  151. # - Or, specify using one of the 9 pre-defined placements such as "tl"
  152. # (for top left), "m" (for middle), "br" (for bottom right)
  153. # - also specify padding from edge amount (optional).
  154. # - Set opacity of watermark (png).
  155. # * ADD BORDER
  156. # * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff)
  157. # * SAVE IMAGE OR OUTPUT TO SCREEN
  158. #
  159. #
  160. # ========================================================================#
  161. class imageLib
  162. {
  163. private $fileName;
  164. private $image;
  165. protected $imageResized;
  166. private $widthOriginal; # Always be the original width
  167. private $heightOriginal;
  168. private $width; # Current width (width after resize)
  169. private $height;
  170. private $imageSize;
  171. private $fileExtension;
  172. private $debug = true;
  173. private $errorArray = array();
  174. private $forceStretch = true;
  175. private $aggresiveSharpening = false;
  176. private $transparentArray = array('.png', '.gif');
  177. private $keepTransparency = true;
  178. private $fillColorArray = array('r'=>255, 'g'=>255, 'b'=>255);
  179. private $sharpenArray = array('jpg');
  180. private $psdReaderPath;
  181. private $filterOverlayPath;
  182. private $isInterlace;
  183. private $captionBoxPositionArray = array();
  184. private $fontDir = 'fonts';
  185. private $cropFromTopPercent = 10;
  186. ## --------------------------------------------------------
  187. function __construct($fileName)
  188. # Author: Jarrod Oberto
  189. # Date: 27-02-08
  190. # Purpose: Constructor
  191. # Param in: $fileName: File name and path.
  192. # Param out: n/a
  193. # Reference:
  194. # Notes:
  195. #
  196. {
  197. if (!$this->testGDInstalled()) { if ($this->debug) { throw new Exception('The GD Library is not installed.'); }else{ throw new Exception(); }};
  198. $this->initialise();
  199. // *** Save the image file name. Only store this incase you want to display it
  200. $this->fileName = $fileName;
  201. $this->fileExtension = fix_strtolower(strrchr($fileName, '.'));
  202. // *** Open up the file
  203. $this->image = $this->openImage($fileName);
  204. // *** Assign here so we don't modify the original
  205. $this->imageResized = $this->image;
  206. // *** If file is an image
  207. if ($this->testIsImage($this->image))
  208. {
  209. // *** Get width and height
  210. $this->width = imagesx($this->image);
  211. $this->widthOriginal = imagesx($this->image);
  212. $this->height = imagesy($this->image);
  213. $this->heightOriginal = imagesy($this->image);
  214. /* Added 15-09-08
  215. * Get the filesize using this build in method.
  216. * Stores an array of size
  217. *
  218. * $this->imageSize[1] = width
  219. * $this->imageSize[2] = height
  220. * $this->imageSize[3] = width x height
  221. *
  222. */
  223. $this->imageSize = getimagesize($this->fileName);
  224. } else {
  225. $this->errorArray[] = 'File is not an image';
  226. }
  227. }
  228. ## --------------------------------------------------------
  229. private function initialise () {
  230. $this->psdReaderPath = dirname(__FILE__) . '/classPhpPsdReader.php';
  231. $this->filterOverlayPath = dirname(__FILE__) . '/filters';
  232. // *** Set if image should be interlaced or not.
  233. $this->isInterlace = false;
  234. }
  235. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  236. Resize
  237. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  238. public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = false, $autoRotate = false)
  239. # Author: Jarrod Oberto
  240. # Date: 27-02-08
  241. # Purpose: Resizes the image
  242. # Param in: $newWidth:
  243. # $newHeight:
  244. # $option: 0 / exact = defined size;
  245. # 1 / portrait = keep aspect set height;
  246. # 2 / landscape = keep aspect set width;
  247. # 3 / auto = auto;
  248. # 4 / crop= resize and crop;
  249. #
  250. # $option can also be an array containing options for
  251. # cropping. E.G., array('crop', 'r')
  252. #
  253. # This array only applies to 'crop' and the 'r' refers to
  254. # "crop right". Other value include; tl, t, tr, l, m (default),
  255. # r, bl, b, br, or you can specify your own co-ords (which
  256. # isn't recommended.
  257. #
  258. # $sharpen: true: sharpen (jpg only);
  259. # false: don't sharpen
  260. # Param out: n/a
  261. # Reference:
  262. # Notes: To clarify the $option input:
  263. # 0 = The exact height and width dimensions you set.
  264. # 1 = Whatever height is passed in will be the height that
  265. # is set. The width will be calculated and set automatically
  266. # to a the value that keeps the original aspect ratio.
  267. # 2 = The same but based on the width. We try make the image the
  268. # biggest size we can while stil fitting inside the box size
  269. # 3 = Depending whether the image is landscape or portrait, this
  270. # will automatically determine whether to resize via
  271. # dimension 1,2 or 0
  272. # 4 = Will resize and then crop the image for best fit
  273. #
  274. # forceStretch can be applied to options 1,2,3 and 4
  275. #
  276. {
  277. // *** We can pass in an array of options to change the crop position
  278. $cropPos = 'm';
  279. if (is_array($option) && fix_strtolower($option[0]) == 'crop') {
  280. $cropPos = $option[1]; # get the crop option
  281. } else if (strpos($option, '-') !== false) {
  282. // *** Or pass in a hyphen seperated option
  283. $optionPiecesArray = explode('-', $option);
  284. $cropPos = end($optionPiecesArray);
  285. }
  286. // *** Check the option is valid
  287. $option = $this->prepOption($option);
  288. // *** Make sure the file passed in is valid
  289. if (!$this->image) { if ($this->debug) { throw new Exception('file ' . $this->getFileName() .' is missing or invalid'); }else{ throw new Exception(); }};
  290. // *** Get optimal width and height - based on $option
  291. $dimensionsArray = $this->getDimensions($newWidth, $newHeight, $option);
  292. $optimalWidth = $dimensionsArray['optimalWidth'];
  293. $optimalHeight = $dimensionsArray['optimalHeight'];
  294. // *** Resample - create image canvas of x, y size
  295. $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
  296. $this->keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized);
  297. imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
  298. // *** If '4', then crop too
  299. if ($option == 4 || $option == 'crop') {
  300. if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight)) {
  301. $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
  302. }
  303. }
  304. // *** If Rotate.
  305. if ($autoRotate) {
  306. $exifData = $this->getExif(false);
  307. if (count($exifData) > 0) {
  308. switch($exifData['orientation']) {
  309. case 8:
  310. $this->imageResized = imagerotate($this->imageResized,90,0);
  311. break;
  312. case 3:
  313. $this->imageResized = imagerotate($this->imageResized,180,0);
  314. break;
  315. case 6:
  316. $this->imageResized = imagerotate($this->imageResized,-90,0);
  317. break;
  318. }
  319. }
  320. }
  321. // *** Sharpen image (if jpg and the user wishes to do so)
  322. if ($sharpen && in_array($this->fileExtension, $this->sharpenArray)) {
  323. // *** Sharpen
  324. $this->sharpen();
  325. }
  326. }
  327. ## --------------------------------------------------------
  328. public function cropImage($newWidth, $newHeight, $cropPos = 'm')
  329. # Author: Jarrod Oberto
  330. # Date: 08-09-11
  331. # Purpose: Crops the image
  332. # Param in: $newWidth: crop with
  333. # $newHeight: crop height
  334. # $cropPos: Can be any of the following:
  335. # tl, t, tr, l, m, r, bl, b, br, auto
  336. # Or:
  337. # a custom position such as '30x50'
  338. # Param out: n/a
  339. # Reference:
  340. # Notes:
  341. #
  342. {
  343. // *** Make sure the file passed in is valid
  344. if (!$this->image) { if ($this->debug) { throw new Exception('file ' . $this->getFileName() .' is missing or invalid'); }else{ throw new Exception(); }};
  345. $this->imageResized = $this->image;
  346. $this->crop($this->width, $this->height, $newWidth, $newHeight, $cropPos);
  347. }
  348. ## --------------------------------------------------------
  349. private function keepTransparancy($width, $height, $im)
  350. # Author: Jarrod Oberto
  351. # Date: 08-04-11
  352. # Purpose: Keep transparency for png and gif image
  353. # Param in:
  354. # Param out: n/a
  355. # Reference:
  356. # Notes:
  357. #
  358. {
  359. // *** If PNG, perform some transparency retention actions (gif untested)
  360. if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency) {
  361. imagealphablending($im, false);
  362. imagesavealpha($im, true);
  363. $transparent = imagecolorallocatealpha($im, 255, 255, 255, 127);
  364. imagefilledrectangle($im, 0, 0, $width, $height, $transparent);
  365. } else {
  366. $color = imagecolorallocate($im, $this->fillColorArray['r'], $this->fillColorArray['g'], $this->fillColorArray['b']);
  367. imagefilledrectangle($im, 0, 0, $width, $height, $color);
  368. }
  369. }
  370. ## --------------------------------------------------------
  371. private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)
  372. # Author: Jarrod Oberto
  373. # Date: 15-09-08
  374. # Purpose: Crops the image
  375. # Param in: $newWidth:
  376. # $newHeight:
  377. # Param out: n/a
  378. # Reference:
  379. # Notes:
  380. #
  381. {
  382. // *** Get cropping co-ordinates
  383. $cropArray = $this->getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
  384. $cropStartX = $cropArray['x'];
  385. $cropStartY = $cropArray['y'];
  386. // *** Crop this bad boy
  387. $crop = imagecreatetruecolor($newWidth , $newHeight);
  388. $this->keepTransparancy($optimalWidth, $optimalHeight, $crop);
  389. imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
  390. $this->imageResized = $crop;
  391. // *** Set new width and height to our variables
  392. $this->width = $newWidth;
  393. $this->height = $newHeight;
  394. }
  395. ## --------------------------------------------------------
  396. private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos='m')
  397. #
  398. # Author: Jarrod Oberto
  399. # Date: July 11
  400. # Purpose: Set the cropping area.
  401. # Params in:
  402. # Params out: (array) the crop x and y co-ordinates.
  403. # Notes: When specifying the exact pixel crop position (eg 10x15), be
  404. # very careful as it's easy to crop out of the image leaving
  405. # black borders.
  406. #
  407. {
  408. $pos = fix_strtolower($pos);
  409. // *** If co-ords have been entered
  410. if (strstr($pos, 'x')) {
  411. $pos = str_replace(' ', '', $pos);
  412. $xyArray = explode('x', $pos);
  413. list($cropStartX, $cropStartY) = $xyArray;
  414. } else {
  415. switch ($pos) {
  416. case 'tl':
  417. $cropStartX = 0;
  418. $cropStartY = 0;
  419. break;
  420. case 't':
  421. $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
  422. $cropStartY = 0;
  423. break;
  424. case 'tr':
  425. $cropStartX = $optimalWidth - $newWidth;
  426. $cropStartY = 0;
  427. break;
  428. case 'l':
  429. $cropStartX = 0;
  430. $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
  431. break;
  432. case 'm':
  433. $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
  434. $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
  435. break;
  436. case 'r':
  437. $cropStartX = $optimalWidth - $newWidth;
  438. $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
  439. break;
  440. case 'bl':
  441. $cropStartX = 0;
  442. $cropStartY = $optimalHeight - $newHeight;
  443. break;
  444. case 'b':
  445. $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
  446. $cropStartY = $optimalHeight - $newHeight;
  447. break;
  448. case 'br':
  449. $cropStartX = $optimalWidth - $newWidth;
  450. $cropStartY = $optimalHeight - $newHeight;
  451. break;
  452. case 'auto':
  453. // *** If image is a portrait crop from top, not center. v1.5
  454. if ($optimalHeight > $optimalWidth) {
  455. $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
  456. $cropStartY = ($this->cropFromTopPercent /100) * $optimalHeight;
  457. } else {
  458. // *** Else crop from the center
  459. $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
  460. $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
  461. }
  462. break;
  463. default:
  464. // *** Default to center
  465. $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
  466. $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
  467. break;
  468. }
  469. }
  470. return array('x' => $cropStartX, 'y' => $cropStartY);
  471. }
  472. ## --------------------------------------------------------
  473. private function getDimensions($newWidth, $newHeight, $option)
  474. # Author: Jarrod Oberto
  475. # Date: 17-11-09
  476. # Purpose: Get new image dimensions based on user specificaions
  477. # Param in: $newWidth:
  478. # $newHeight:
  479. # Param out: Array of new width and height values
  480. # Reference:
  481. # Notes: If $option = 3 then this function is call recursivly
  482. #
  483. # To clarify the $option input:
  484. # 0 = The exact height and width dimensions you set.
  485. # 1 = Whatever height is passed in will be the height that
  486. # is set. The width will be calculated and set automatically
  487. # to a the value that keeps the original aspect ratio.
  488. # 2 = The same but based on the width.
  489. # 3 = Depending whether the image is landscape or portrait, this
  490. # will automatically determine whether to resize via
  491. # dimension 1,2 or 0.
  492. # 4 = Resize the image as much as possible, then crop the
  493. # remainder.
  494. {
  495. switch (strval($option))
  496. {
  497. case '0':
  498. case 'exact':
  499. $optimalWidth = $newWidth;
  500. $optimalHeight= $newHeight;
  501. break;
  502. case '1':
  503. case 'portrait':
  504. $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
  505. $optimalWidth = $dimensionsArray['optimalWidth'];
  506. $optimalHeight = $dimensionsArray['optimalHeight'];
  507. break;
  508. case '2':
  509. case 'landscape':
  510. $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
  511. $optimalWidth = $dimensionsArray['optimalWidth'];
  512. $optimalHeight = $dimensionsArray['optimalHeight'];
  513. break;
  514. case '3':
  515. case 'auto':
  516. $dimensionsArray = $this->getSizeByAuto($newWidth, $newHeight);
  517. $optimalWidth = $dimensionsArray['optimalWidth'];
  518. $optimalHeight = $dimensionsArray['optimalHeight'];
  519. break;
  520. case '4':
  521. case 'crop':
  522. $dimensionsArray = $this->getOptimalCrop($newWidth, $newHeight);
  523. $optimalWidth = $dimensionsArray['optimalWidth'];
  524. $optimalHeight = $dimensionsArray['optimalHeight'];
  525. break;
  526. }
  527. return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
  528. }
  529. ## --------------------------------------------------------
  530. private function getSizeByFixedHeight($newWidth, $newHeight)
  531. {
  532. // *** If forcing is off...
  533. if (!$this->forceStretch) {
  534. // *** ...check if actual height is less than target height
  535. if ($this->height < $newHeight) {
  536. return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
  537. }
  538. }
  539. $ratio = $this->width / $this->height;
  540. $newWidth = $newHeight * $ratio;
  541. //return $newWidth;
  542. return array('optimalWidth' => $newWidth, 'optimalHeight' => $newHeight);
  543. }
  544. ## --------------------------------------------------------
  545. private function getSizeByFixedWidth($newWidth, $newHeight)
  546. {
  547. // *** If forcing is off...
  548. if (!$this->forceStretch) {
  549. // *** ...check if actual width is less than target width
  550. if ($this->width < $newWidth) {
  551. return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
  552. }
  553. }
  554. $ratio = $this->height / $this->width;
  555. $newHeight = $newWidth * $ratio;
  556. //return $newHeight;
  557. return array('optimalWidth' => $newWidth, 'optimalHeight' => $newHeight);
  558. }
  559. ## --------------------------------------------------------
  560. private function getSizeByAuto($newWidth, $newHeight)
  561. # Author: Jarrod Oberto
  562. # Date: 19-08-08
  563. # Purpose: Depending on the height, choose to resize by 0, 1, or 2
  564. # Param in: The new height and new width
  565. # Notes:
  566. #
  567. {
  568. // *** If forcing is off...
  569. if (!$this->forceStretch) {
  570. // *** ...check if actual size is less than target size
  571. if ($this->width < $newWidth && $this->height < $newHeight) {
  572. return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
  573. }
  574. }
  575. if ($this->height < $this->width)
  576. // *** Image to be resized is wider (landscape)
  577. {
  578. //$optimalWidth = $newWidth;
  579. //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
  580. $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
  581. $optimalWidth = $dimensionsArray['optimalWidth'];
  582. $optimalHeight = $dimensionsArray['optimalHeight'];
  583. }
  584. elseif ($this->height > $this->width)
  585. // *** Image to be resized is taller (portrait)
  586. {
  587. //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
  588. //$optimalHeight= $newHeight;
  589. $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
  590. $optimalWidth = $dimensionsArray['optimalWidth'];
  591. $optimalHeight = $dimensionsArray['optimalHeight'];
  592. }
  593. else
  594. // *** Image to be resizerd is a square
  595. {
  596. if ($newHeight < $newWidth) {
  597. //$optimalWidth = $newWidth;
  598. //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
  599. $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
  600. $optimalWidth = $dimensionsArray['optimalWidth'];
  601. $optimalHeight = $dimensionsArray['optimalHeight'];
  602. } else if ($newHeight > $newWidth) {
  603. //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
  604. //$optimalHeight= $newHeight;
  605. $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
  606. $optimalWidth = $dimensionsArray['optimalWidth'];
  607. $optimalHeight = $dimensionsArray['optimalHeight'];
  608. } else {
  609. // *** Sqaure being resized to a square
  610. $optimalWidth = $newWidth;
  611. $optimalHeight= $newHeight;
  612. }
  613. }
  614. return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
  615. }
  616. ## --------------------------------------------------------
  617. private function getOptimalCrop($newWidth, $newHeight)
  618. # Author: Jarrod Oberto
  619. # Date: 17-11-09
  620. # Purpose: Get optimal crop dimensions
  621. # Param in: width and height as requested by user (fig 3)
  622. # Param out: Array of optimal width and height (fig 2)
  623. # Reference:
  624. # Notes: The optimal width and height return are not the same as the
  625. # same as the width and height passed in. For example:
  626. #
  627. #
  628. # |-----------------| |------------| |-------|
  629. # | | => |**| |**| => | |
  630. # | | |**| |**| | |
  631. # | | |------------| |-------|
  632. # |-----------------|
  633. # original optimal crop
  634. # size size size
  635. # Fig 1 2 3
  636. #
  637. # 300 x 250 150 x 125 150 x 100
  638. #
  639. # The optimal size is the smallest size (that is closest to the crop size)
  640. # while retaining proportion/ratio.
  641. #
  642. # The crop size is the optimal size that has been cropped on one axis to
  643. # make the image the exact size specified by the user.
  644. #
  645. # * represent cropped area
  646. #
  647. {
  648. // *** If forcing is off...
  649. if (!$this->forceStretch) {
  650. // *** ...check if actual size is less than target size
  651. if ($this->width < $newWidth && $this->height < $newHeight) {
  652. return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
  653. }
  654. }
  655. $heightRatio = $this->height / $newHeight;
  656. $widthRatio = $this->width / $newWidth;
  657. if ($heightRatio < $widthRatio) {
  658. $optimalRatio = $heightRatio;
  659. } else {
  660. $optimalRatio = $widthRatio;
  661. }
  662. $optimalHeight = round( $this->height / $optimalRatio );
  663. $optimalWidth = round( $this->width / $optimalRatio );
  664. return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
  665. }
  666. ## --------------------------------------------------------
  667. private function sharpen()
  668. # Author: Jarrod Oberto
  669. # Date: 08 04 2011
  670. # Purpose: Sharpen image
  671. # Param in: n/a
  672. # Param out: n/a
  673. # Reference:
  674. # Notes:
  675. # Credit: Incorporates Joe Lencioni (August 6, 2008) code
  676. {
  677. if (version_compare(PHP_VERSION, '5.1.0') >= 0) {
  678. // ***
  679. if ($this->aggresiveSharpening) { # A more aggressive sharpening solution
  680. $sharpenMatrix = array( array( -1, -1, -1 ),
  681. array( -1, 16, -1 ),
  682. array( -1, -1, -1 ) );
  683. $divisor = 8;
  684. $offset = 0;
  685. imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
  686. }
  687. else # More subtle and personally more desirable
  688. {
  689. $sharpness = $this->findSharp($this->widthOriginal, $this->width);
  690. $sharpenMatrix = array(
  691. array(-1, -2, -1),
  692. array(-2, $sharpness + 12, -2), //Lessen the effect of a filter by increasing the value in the center cell
  693. array(-1, -2, -1)
  694. );
  695. $divisor = $sharpness; // adjusts brightness
  696. $offset = 0;
  697. imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
  698. }
  699. }
  700. else
  701. {
  702. if ($this->debug) { throw new Exception('Sharpening required PHP 5.1.0 or greater.'); }
  703. }
  704. }
  705. ## --------------------------------------------------------
  706. private function sharpen2($level)
  707. {
  708. $sharpenMatrix = array(
  709. array($level, $level, $level),
  710. array($level, (8*$level)+1, $level), //Lessen the effect of a filter by increasing the value in the center cell
  711. array($level, $level, $level)
  712. );
  713. }
  714. ## --------------------------------------------------------
  715. private function findSharp($orig, $final)
  716. # Author: Ryan Rud (http://adryrun.com)
  717. # Purpose: Find optimal sharpness
  718. # Param in: n/a
  719. # Param out: n/a
  720. # Reference:
  721. # Notes:
  722. #
  723. {
  724. $final = $final * (750.0 / $orig);
  725. $a = 52;
  726. $b = -0.27810650887573124;
  727. $c = .00047337278106508946;
  728. $result = $a + $b * $final + $c * $final * $final;
  729. return max(round($result), 0);
  730. }
  731. ## --------------------------------------------------------
  732. private function prepOption($option)
  733. # Author: Jarrod Oberto
  734. # Purpose: Prep option like change the passed in option to lowercase
  735. # Param in: (str/int) $option: eg. 'exact', 'crop'. 0, 4
  736. # Param out: lowercase string
  737. # Reference:
  738. # Notes:
  739. #
  740. {
  741. if (is_array($option)) {
  742. if (fix_strtolower($option[0]) == 'crop' && count($option) == 2) {
  743. return 'crop';
  744. } else {
  745. throw new Exception('Crop resize option array is badly formatted.');
  746. }
  747. } else if (strpos($option, 'crop') !== false) {
  748. return 'crop';
  749. }
  750. if (is_string($option)) {
  751. return fix_strtolower($option);
  752. }
  753. return $option;
  754. }
  755. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  756. Presets
  757. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  758. #
  759. # Preset are pre-defined templates you can apply to your image.
  760. #
  761. # These are inteded to be applied to thumbnail images.
  762. #
  763. public function borderPreset($preset)
  764. {
  765. switch ($preset)
  766. {
  767. case 'simple':
  768. $this->addBorder(7, '#fff');
  769. $this->addBorder(6, '#f2f1f0');
  770. $this->addBorder(2, '#fff');
  771. $this->addBorder(1, '#ccc');
  772. break;
  773. default:
  774. break;
  775. }
  776. }
  777. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  778. Draw border
  779. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  780. public function addBorder($thickness = 1, $rgbArray = array(255, 255, 255))
  781. # Author: Jarrod Oberto
  782. # Date: 05-05-11
  783. # Purpose: Add a border to the image
  784. # Param in:
  785. # Param out:
  786. # Reference:
  787. # Notes: This border is added to the INSIDE of the image
  788. #
  789. {
  790. if ($this->imageResized) {
  791. $rgbArray = $this->formatColor($rgbArray);
  792. $r = $rgbArray['r'];
  793. $g = $rgbArray['g'];
  794. $b = $rgbArray['b'];
  795. $x1 = 0;
  796. $y1 = 0;
  797. $x2 = ImageSX($this->imageResized) - 1;
  798. $y2 = ImageSY($this->imageResized) - 1;
  799. $rgbArray = ImageColorAllocate($this->imageResized, $r, $g, $b);
  800. for($i = 0; $i < $thickness; $i++) {
  801. ImageRectangle($this->imageResized, $x1++, $y1++, $x2--, $y2--, $rgbArray);
  802. }
  803. }
  804. }
  805. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  806. Gray Scale
  807. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  808. public function greyScale()
  809. # Author: Jarrod Oberto
  810. # Date: 07-05-2011
  811. # Purpose: Make image greyscale
  812. # Param in: n/a
  813. # Param out:
  814. # Reference:
  815. # Notes:
  816. #
  817. {
  818. if ($this->imageResized) {
  819. imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
  820. }
  821. }
  822. ## --------------------------------------------------------
  823. public function greyScaleEnhanced()
  824. # Author: Jarrod Oberto
  825. # Date: 07-05-2011
  826. # Purpose: Make image greyscale
  827. # Param in: n/a
  828. # Param out:
  829. # Reference:
  830. # Notes:
  831. #
  832. {
  833. if ($this->imageResized) {
  834. imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
  835. imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
  836. imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2);
  837. $this->sharpen($this->width);
  838. }
  839. }
  840. ## --------------------------------------------------------
  841. public function greyScaleDramatic()
  842. # Alias of gd_filter_monopin
  843. {
  844. $this->gd_filter_monopin();
  845. }
  846. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  847. Black 'n White
  848. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  849. public function blackAndWhite()
  850. # Author: Jarrod Oberto
  851. # Date: 07-05-2011
  852. # Purpose: Make image black and white
  853. # Param in: n/a
  854. # Param out:
  855. # Reference:
  856. # Notes:
  857. #
  858. {
  859. if ($this->imageResized) {
  860. imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
  861. imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000);
  862. }
  863. }
  864. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  865. Negative
  866. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  867. public function negative()
  868. # Author: Jarrod Oberto
  869. # Date: 07-05-2011
  870. # Purpose: Make image negative
  871. # Param in: n/a
  872. # Param out:
  873. # Reference:
  874. # Notes:
  875. #
  876. {
  877. if ($this->imageResized) {
  878. imagefilter($this->imageResized, IMG_FILTER_NEGATE);
  879. }
  880. }
  881. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  882. Sepia
  883. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  884. public function sepia()
  885. # Author: Jarrod Oberto
  886. # Date: 07-05-2011
  887. # Purpose: Make image sepia
  888. # Param in: n/a
  889. # Param out:
  890. # Reference:
  891. # Notes:
  892. #
  893. {
  894. if ($this->imageResized) {
  895. imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
  896. imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10);
  897. imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20);
  898. imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15);
  899. }
  900. }
  901. ## --------------------------------------------------------
  902. public function sepia2()
  903. {
  904. if ($this->imageResized) {
  905. $total = imagecolorstotal( $this->imageResized );
  906. for ( $i = 0; $i < $total; $i++ ) {
  907. $index = imagecolorsforindex( $this->imageResized, $i );
  908. $red = ( $index["red"] * 0.393 + $index["green"] * 0.769 + $index["blue"] * 0.189 ) / 1.351;
  909. $green = ( $index["red"] * 0.349 + $index["green"] * 0.686 + $index["blue"] * 0.168 ) / 1.203;
  910. $blue = ( $index["red"] * 0.272 + $index["green"] * 0.534 + $index["blue"] * 0.131 ) / 2.140;
  911. imagecolorset( $this->imageResized, $i, $red, $green, $blue );
  912. }
  913. }
  914. }
  915. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  916. Vintage
  917. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  918. public function vintage()
  919. # Alias of gd_filter_monopin
  920. {
  921. $this->gd_filter_vintage();
  922. }
  923. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  924. Presets By Marc Hibbins
  925. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  926. /** Apply 'Monopin' preset */
  927. public function gd_filter_monopin()
  928. {
  929. if ($this->imageResized) {
  930. imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
  931. imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15);
  932. imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
  933. $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 100);
  934. }
  935. }
  936. ## --------------------------------------------------------
  937. public function gd_filter_vintage()
  938. {
  939. if ($this->imageResized) {
  940. $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 45);
  941. imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20);
  942. imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35);
  943. imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35);
  944. imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7);
  945. $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'scratch', 10);
  946. }
  947. }
  948. ## --------------------------------------------------------
  949. /** Apply a PNG overlay */
  950. private function gd_apply_overlay($im, $type, $amount)
  951. #
  952. # Original Author: Marc Hibbins
  953. # License: Attribution-ShareAlike 3.0
  954. # Purpose:
  955. # Params in:
  956. # Params out:
  957. # Notes:
  958. #
  959. {
  960. $width = imagesx($im);
  961. $height = imagesy($im);
  962. $filter = imagecreatetruecolor($width, $height);
  963. imagealphablending($filter, false);
  964. imagesavealpha($filter, true);
  965. $transparent = imagecolorallocatealpha($filter, 255, 255, 255, 127);
  966. imagefilledrectangle($filter, 0, 0, $width, $height, $transparent);
  967. // *** Resize overlay
  968. $overlay = $this->filterOverlayPath . '/' . $type . '.png';
  969. $png = imagecreatefrompng($overlay);
  970. imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, imagesx($png), imagesy($png));
  971. $comp = imagecreatetruecolor($width, $height);
  972. imagecopy($comp, $im, 0, 0, 0, 0, $width, $height);
  973. imagecopy($comp, $filter, 0, 0, 0, 0, $width, $height);
  974. imagecopymerge($im, $comp, 0, 0, 0, 0, $width, $height, $amount);
  975. imagedestroy($comp);
  976. return $im;
  977. }
  978. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  979. Colorise
  980. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  981. public function image_colorize($rgb) {
  982. imageTrueColorToPalette($this->imageResized,true,256);
  983. $numColors = imageColorsTotal($this->imageResized);
  984. for ($x = 0; $x < $numColors; $x++) {
  985. list($r,$g,$b) = array_values(imageColorsForIndex($this->imageResized,$x));
  986. // calculate grayscale in percent
  987. $grayscale = ($r + $g + $b) / 3 / 0xff;
  988. imageColorSet($this->imageResized,$x,
  989. $grayscale * $rgb[0],
  990. $grayscale * $rgb[1],
  991. $grayscale * $rgb[2]
  992. );
  993. }
  994. return true;
  995. }
  996. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  997. Reflection
  998. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  999. public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = false, $bgColor = '#fff', $stretch=false, $divider = 0)
  1000. {
  1001. // *** Convert color
  1002. $rgbArray = $this->formatColor($bgColor);
  1003. $r = $rgbArray['r'];
  1004. $g = $rgbArray['g'];
  1005. $b = $rgbArray['b'];
  1006. $im = $this->imageResized;
  1007. $li = imagecreatetruecolor($this->width, 1);
  1008. $bgc = imagecolorallocate($li, $r, $g, $b);
  1009. imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc);
  1010. $bg = imagecreatetruecolor($this->width, $reflectionHeight);
  1011. $wh = imagecolorallocate($im, 255, 255, 255);
  1012. $im = imagerotate($im, -180, $wh);
  1013. imagecopyresampled($bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
  1014. $im = $bg;
  1015. $bg = imagecreatetruecolor($this->width, $reflectionHeight);
  1016. for ($x = 0; $x < $this->width; $x++) {
  1017. imagecopy($bg, $im, $x, 0, $this->width-$x -1, 0, 1, $reflectionHeight);
  1018. }
  1019. $im = $bg;
  1020. $transaprencyAmount = $this->invertTransparency($startingTransparency, 100);
  1021. // *** Fade
  1022. if ($stretch) {
  1023. $step = 100/($reflectionHeight + $startingTransparency);
  1024. } else{
  1025. $step = 100/$reflectionHeight;
  1026. }
  1027. for($i=0; $i<=$reflectionHeight; $i++){
  1028. if($startingTransparency>100) $startingTransparency = 100;
  1029. if($startingTransparency< 1) $startingTransparency = 1;
  1030. imagecopymerge($bg, $li, 0, $i, 0, 0, $this->width, 1, $startingTransparency);
  1031. $startingTransparency+=$step;
  1032. }
  1033. // *** Apply fade
  1034. imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); // Divider
  1035. // *** width, height of reflection.
  1036. $x = imagesx($im);
  1037. $y = imagesy($im);
  1038. // *** Determines if the reflection should be displayed inside or outside the image
  1039. if ($inside) {
  1040. // Create new blank image with sizes.
  1041. $final = imagecreatetruecolor($this->width, $this->height);
  1042. imagecopymerge ($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100);
  1043. imagecopymerge ($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100);
  1044. } else {
  1045. // Create new blank image with sizes.
  1046. $final = imagecreatetruecolor($this->width, $this->height + $y);
  1047. imagecopymerge ($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100);
  1048. imagecopymerge ($final, $im, 0, $this->height, 0, 0, $x, $y, 100);
  1049. }
  1050. $this->imageResized = $final;
  1051. imagedestroy($li);
  1052. imagedestroy($im);
  1053. }
  1054. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1055. Rotate
  1056. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1057. public function rotate($value = 90, $bgColor = 'transparent')
  1058. # Author: Jarrod Oberto
  1059. # Date: 07-05-2011
  1060. # Purpose: Rotate image
  1061. # Param in: (mixed) $degrees: (int) number of degress to rotate image
  1062. # (str) param "left": rotate left
  1063. # (str) param "right": rotate right
  1064. # (str) param "upside": upside-down image
  1065. # Param out:
  1066. # Reference:
  1067. # Notes: The default direction of imageRotate() is counter clockwise.
  1068. #
  1069. {
  1070. if ($this->imageResized) {
  1071. if (is_integer($value)) {
  1072. $degrees = $value;
  1073. }
  1074. // *** Convert color
  1075. $rgbArray = $this->formatColor($bgColor);
  1076. $r = $rgbArray['r'];
  1077. $g = $rgbArray['g'];
  1078. $b = $rgbArray['b'];
  1079. if (isset($rgbArray['a'])) {$a = $rgbArray['a']; }
  1080. if (is_string($value)) {
  1081. $value = fix_strtolower($value);
  1082. switch ($value) {
  1083. case 'left':
  1084. $degrees = 90;
  1085. break;
  1086. case 'right':
  1087. $degrees = 270;
  1088. break;
  1089. case 'upside':
  1090. $degrees = 180;
  1091. break;
  1092. default:
  1093. break;
  1094. }
  1095. }
  1096. // *** The default direction of imageRotate() is counter clockwise
  1097. // * This makes it clockwise
  1098. $degrees = 360 - $degrees;
  1099. // *** Create background color
  1100. $bg = ImageColorAllocateAlpha($this->imageResized, $r, $g, $b, $a);
  1101. // *** Fill with background
  1102. ImageFill($this->imageResized, 0, 0 , $bg);
  1103. // *** Rotate
  1104. $this->imageResized = imagerotate($this->imageResized, $degrees, $bg); // Rotate 45 degrees and allocated the transparent colour as the one to make transparent (obviously)
  1105. // Ensure alpha transparency
  1106. ImageSaveAlpha($this->imageResized,true);
  1107. }
  1108. }
  1109. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1110. Round corners
  1111. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1112. public function roundCorners($radius = 5, $bgColor = 'transparent')
  1113. # Author: Jarrod Oberto
  1114. # Date: 19-05-2011
  1115. # Purpose: Create rounded corners on your image
  1116. # Param in: (int) radius = the amount of curvature
  1117. # (mixed) $bgColor = the corner background color
  1118. # Param out: n/a
  1119. # Reference:
  1120. # Notes:
  1121. #
  1122. {
  1123. // *** Check if the user wants transparency
  1124. $isTransparent = false;
  1125. if (!is_array($bgColor)) {
  1126. if (fix_strtolower($bgColor) == 'transparent') {
  1127. $isTransparent = true;
  1128. }
  1129. }
  1130. // *** If we use transparency, we need to color our curved mask with a unique color
  1131. if ($isTransparent) {
  1132. $bgColor = $this->findUnusedGreen();
  1133. }
  1134. // *** Convert color
  1135. $rgbArray = $this->formatColor($bgColor);
  1136. $r = $rgbArray['r'];
  1137. $g = $rgbArray['g'];
  1138. $b = $rgbArray['b'];
  1139. if (isset($rgbArray['a'])) {$a = $rgbArray['a']; }
  1140. // *** Create top-left corner mask (square)
  1141. $cornerImg = imagecreatetruecolor($radius, $radius);
  1142. //$cornerImg = imagecreate($radius, $radius);
  1143. //imagealphablending($cornerImg, true);
  1144. //imagesavealpha($cornerImg, true);
  1145. //imagealphablending($this->imageResized, false);
  1146. //imagesavealpha($this->imageResized, true);
  1147. // *** Give it a color
  1148. $maskColor = imagecolorallocate($cornerImg, 0, 0, 0);
  1149. // *** Replace the mask color (black) to transparent
  1150. imagecolortransparent($cornerImg, $maskColor);
  1151. // *** Create the image background color
  1152. $imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b);
  1153. // *** Fill the corner area to the user defined color
  1154. imagefill($cornerImg, 0, 0, $imagebgColor);
  1155. imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor );
  1156. // *** Map to top left corner
  1157. imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl
  1158. // *** Map rounded corner to other corners by rotating and applying the mask
  1159. $cornerImg = imagerotate($cornerImg, 90, 0);
  1160. imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl
  1161. $cornerImg = imagerotate($cornerImg, 90, 0);
  1162. imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br
  1163. $cornerImg = imagerotate($cornerImg, 90, 0);
  1164. imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr
  1165. // *** If corners are to be transparent, we fill our chromakey color as transparent.
  1166. if ($isTransparent) {
  1167. //imagecolortransparent($this->imageResized, $imagebgColor);
  1168. $this->imageResized = $this->transparentImage($this->imageResized);
  1169. imagesavealpha($this->imageResized, true);
  1170. }
  1171. }
  1172. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1173. Shadow
  1174. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1175. public function addShadow($shadowAngle=45, $blur=15, $bgColor='transparent')
  1176. #
  1177. # Author: Jarrod Oberto (Adapted from Pascal Naidon)
  1178. # Ref: http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en
  1179. # Purpose: Add a drop shadow to your image
  1180. # Params in: (int) $angle: the angle of the shadow
  1181. # (int) $blur: the blur distance
  1182. # (mixed) $bgColor: the color of the background
  1183. # Params out:
  1184. # Notes:
  1185. #
  1186. {
  1187. // *** A higher number results in a smoother shadow
  1188. define('STEPS', $blur*2);
  1189. // *** Set the shadow distance
  1190. $shadowDistance = $blur*0.25;
  1191. // *** Set blur width and height
  1192. $blurWidth = $blurHeight = $blur;
  1193. if ($shadowAngle == 0) {
  1194. $distWidth = 0;
  1195. $distHeight = 0;
  1196. } else {
  1197. $distWidth = $shadowDistance * cos(deg2rad($shadowAngle));
  1198. $distHeight = $shadowDistance * sin(deg2rad($shadowAngle));
  1199. }
  1200. // *** Convert color
  1201. if (fix_strtolower($bgColor) != 'transparent') {
  1202. $rgbArray = $this->formatColor($bgColor);
  1203. $r0 = $rgbArray['r'];
  1204. $g0 = $rgbArray['g'];
  1205. $b0 = $rgbArray['b'];
  1206. }
  1207. $image = $this->imageResized;
  1208. $width = $this->width;
  1209. $height = $this->height;
  1210. $newImage = imagecreatetruecolor($width, $height);
  1211. imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
  1212. // *** RGB
  1213. $rgb = imagecreatetruecolor($width+$blurWidth,$height+$blurHeight);
  1214. $colour = imagecolorallocate($rgb, 0, 0, 0);
  1215. imagefilledrectangle($rgb, 0, 0, $width+$blurWidth, $height+$blurHeight, $colour);
  1216. $colour = imagecolorallocate($rgb, 255, 255, 255);
  1217. //imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
  1218. imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
  1219. //imagecopymerge($rgb, $newImage, 1+$blurWidth*0.5-$distWidth, 1+$blurHeight*0.5-$distHeight, 0,0, $width, $height, 100);
  1220. imagecopymerge($rgb, $newImage, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, 0,0, $width+$blurWidth, $height+$blurHeight, 100);
  1221. // *** Shadow (alpha)
  1222. $shadow = imagecreatetruecolor($width+$blurWidth,$height+$blurHeight);
  1223. imagealphablending($shadow, false);
  1224. $colour = imagecolorallocate($shadow, 0, 0, 0);
  1225. imagefilledrectangle($shadow, 0, 0, $width+$blurWidth, $height+$blurHeight, $colour);
  1226. for($i=0;$i<=STEPS;$i++) {
  1227. $t = ((1.0*$i)/STEPS);
  1228. $intensity = 255*$t*$t;
  1229. $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
  1230. $points = array(
  1231. $blurWidth*$t, $blurHeight, // Point 1 (x, y)
  1232. $blurWidth, $blurHeight*$t, // Point 2 (x, y)
  1233. $width, $blurHeight*$t, // Point 3 (x, y)
  1234. $width+$blurWidth*(1-$t), $blurHeight, // Point 4 (x, y)
  1235. $width+$blurWidth*(1-$t), $height, // Point 5 (x, y)
  1236. $width, $height+$blurHeight*(1-$t), // Point 6 (x, y)
  1237. $blurWidth, $height+$blurHeight*(1-$t), // Point 7 (x, y)
  1238. $blurWidth*$t, $height // Point 8 (x, y)
  1239. );
  1240. imagepolygon($shadow, $points, 8, $colour);
  1241. }
  1242. for($i=0;$i<=STEPS;$i++) {
  1243. $t = ((1.0*$i)/STEPS);
  1244. $intensity = 255*$t*$t;
  1245. $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
  1246. imagefilledarc($shadow, $blurWidth-1, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 180, 268, $colour, IMG_ARC_PIE);
  1247. imagefilledarc($shadow, $width, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 270, 358, $colour, IMG_ARC_PIE);
  1248. imagefilledarc($shadow, $width, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 0, 90, $colour, IMG_ARC_PIE);
  1249. imagefilledarc($shadow, $blurWidth-1, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 90, 180, $colour, IMG_ARC_PIE);
  1250. }
  1251. $colour = imagecolorallocate($shadow, 255, 255, 255);
  1252. imagefilledrectangle($shadow, $blurWidth, $blurHeight, $width, $height, $colour);
  1253. imagefilledrectangle($shadow, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-1-$distWidth, $height+$blurHeight*0.5-1-$distHeight, $colour);
  1254. // *** The magic
  1255. imagealphablending($rgb, false);
  1256. for ($theX=0;$theX<imagesx($rgb);$theX++){
  1257. for ($theY=0;$theY<imagesy($rgb);$theY++){
  1258. // *** Get the RGB values for every pixel of the RGB image
  1259. $colArray = imagecolorat($rgb,$theX,$theY);
  1260. $r = ($colArray >> 16) & 0xFF;
  1261. $g = ($colArray >> 8) & 0xFF;
  1262. $b = $colArray & 0xFF;
  1263. // *** Get the alpha value for every pixel of the shadow image
  1264. $colArray = imagecolorat($shadow,$theX,$theY);
  1265. $a = $colArray & 0xFF;
  1266. $a = 127-floor($a/2);
  1267. $t = $a/128.0;
  1268. // *** Create color
  1269. if(fix_strtolower($bgColor) == 'transparent') {
  1270. $myColour = imagecolorallocatealpha($rgb,$r,$g,$b,$a);
  1271. } else {
  1272. $myColour = imagecolorallocate($rgb,$r*(1.0-$t)+$r0*$t,$g*(1.0-$t)+$g0*$t,$b*(1.0-$t)+$b0*$t);
  1273. }
  1274. // *** Add color to new rgb image
  1275. imagesetpixel($rgb, $theX, $theY, $myColour);
  1276. }
  1277. }
  1278. imagealphablending($rgb, true);
  1279. imagesavealpha($rgb, true);
  1280. $this->imageResized = $rgb;
  1281. imagedestroy($image);
  1282. imagedestroy($newImage);
  1283. imagedestroy($shadow);
  1284. }
  1285. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1286. Add Caption Box
  1287. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1288. public function addCaptionBox($side='b', $thickness=50, $padding=0, $bgColor='#000', $transaprencyAmount=30)
  1289. #
  1290. # Author: Jarrod Oberto
  1291. # Date: 26 May 2011
  1292. # Purpose: Add a caption box
  1293. # Params in: (str) $side: the side to add the caption box (t, r, b, or l).
  1294. # (int) $thickness: how thick you want the caption box to be.
  1295. # (mixed) $bgColor: The color of the caption box.
  1296. # (int) $transaprencyAmount: The amount of transparency to be
  1297. # applied.
  1298. # Params out: n/a
  1299. # Notes:
  1300. #
  1301. {
  1302. $side = fix_strtolower($side);
  1303. // *** Convert color
  1304. $rgbArray = $this->formatColor($bgColor);
  1305. $r = $rgbArray['r'];
  1306. $g = $rgbArray['g'];
  1307. $b = $rgbArray['b'];
  1308. $positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding);
  1309. // *** Store incase we want to use method addTextToCaptionBox()
  1310. $this->captionBoxPositionArray = $positionArray;
  1311. $transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, false);
  1312. $transparent = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount);
  1313. imagefilledrectangle($this->imageResized, $positionArray['x1'], $positionArray['y1'], $positionArray['x2'], $positionArray['y2'], $transparent);
  1314. }
  1315. ## --------------------------------------------------------
  1316. public function addTextToCaptionBox($text, $fontColor='#fff', $fontSize = 12, $angle = 0, $font = null)
  1317. #
  1318. # Author: Jarrod Oberto
  1319. # Date: 03 Aug 11
  1320. # Purpose: Simplify adding text to a caption box by automatically
  1321. # locating the center of the caption box
  1322. # Params in: The usually text paams (less a couple)
  1323. # Params out: n/a
  1324. # Notes:
  1325. #
  1326. {
  1327. // *** Get the caption box measurements
  1328. if (count($this->captionBoxPositionArray) == 4) {
  1329. $x1 = $this->captionBoxPositionArray['x1'];
  1330. $x2 = $this->captionBoxPositionArray['x2'];
  1331. $y1 = $this->captionBoxPositionArray['y1'];
  1332. $y2 = $this->captionBoxPositionArray['y2'];
  1333. } else {
  1334. if ($this->debug) { throw new Exception('No caption box found.'); }else{ return false; }
  1335. }
  1336. // *** Get text font
  1337. $font = $this->getTextFont($font);
  1338. // *** Get text size
  1339. $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
  1340. $textWidth = $textSizeArray['width'];
  1341. $textHeight = $textSizeArray['height'];
  1342. // *** Find the width/height middle points
  1343. $boxXMiddle = (($x2 - $x1) / 2);
  1344. $boxYMiddle = (($y2 - $y1) / 2);
  1345. // *** Box middle - half the text width/height
  1346. $xPos = ($x1 + $boxXMiddle) - ($textWidth/2);
  1347. $yPos = ($y1 + $boxYMiddle) - ($textHeight/2);
  1348. $pos = $xPos . 'x' . $yPos;
  1349. $this->addText($text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font);
  1350. }
  1351. ## --------------------------------------------------------
  1352. private function calculateCaptionBoxPosition($side, $thickness, $padding)
  1353. {
  1354. $positionArray = array();
  1355. switch ($side) {
  1356. case 't':
  1357. $positionArray['x1'] = 0;
  1358. $positionArray['y1'] = $padding;
  1359. $positionArray['x2'] = $this->width;
  1360. $positionArray['y2'] = $thickness + $padding;
  1361. break;
  1362. case 'r':
  1363. $positionArray['x1'] = $this->width - $thickness - $padding;
  1364. $positionArray['y1'] = 0;
  1365. $positionArray['x2'] = $this->width - $padding;
  1366. $positionArray['y2'] = $this->height;
  1367. break;
  1368. case 'b':
  1369. $positionArray['x1'] = 0;
  1370. $positionArray['y1'] = $this->height - $thickness - $padding;
  1371. $positionArray['x2'] = $this->width;
  1372. $positionArray['y2'] = $this->height - $padding;
  1373. break;
  1374. case 'l':
  1375. $positionArray['x1'] = $padding;
  1376. $positionArray['y1'] = 0;
  1377. $positionArray['x2'] = $thickness + $padding;
  1378. $positionArray['y2'] = $this->height;
  1379. break;
  1380. default:
  1381. break;
  1382. }
  1383. return $positionArray;
  1384. }
  1385. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1386. Get EXIF Data
  1387. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1388. public function getExif($debug=false)
  1389. # Author: Jarrod Oberto
  1390. # Date: 07-05-2011
  1391. # Purpose: Get image EXIF data
  1392. # Param in: n/a
  1393. # Param out: An associate array of EXIF data
  1394. # Reference:
  1395. # Notes:
  1396. # 23 May 13 : added orientation flag -jco
  1397. #
  1398. {
  1399. if (!$this->debug || !$debug) { $debug = false; }
  1400. // *** Check all is good - check the EXIF library exists and the file exists, too.
  1401. if (!$this->testEXIFInstalled()) { if ($debug) { throw new Exception('The EXIF Library is not installed.'); }else{ return array(); }};
  1402. if (!file_exists($this->fileName)) { if ($debug) { throw new Exception('Image not found.'); }else{ return array(); }};
  1403. if ($this->fileExtension != '.jpg') { if ($debug) { throw new Exception('Metadata not supported for this image type.'); }else{ return array(); }};
  1404. $exifData = exif_read_data($this->fileName, 'IFD0');
  1405. // *** Format the apperture value
  1406. $ev = $exifData['ApertureValue'];
  1407. $apPeicesArray = explode('/', $ev);
  1408. if (count($apPeicesArray) == 2) {
  1409. $apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . ' EV';
  1410. } else { $apertureValue = '';}
  1411. // *** Format the focal length
  1412. $focalLength = $exifData['FocalLength'];
  1413. $flPeicesArray = explode('/', $focalLength);
  1414. if (count($flPeicesArray) == 2) {
  1415. $focalLength = $flPeicesArray[0] / $flPeicesArray[1] . '.0 mm';
  1416. } else { $focalLength = '';}
  1417. // *** Format fNumber
  1418. $fNumber = $exifData['FNumber'];
  1419. $fnPeicesArray = explode('/', $fNumber);
  1420. if (count($fnPeicesArray) == 2) {
  1421. $fNumber = $fnPeicesArray[0] / $fnPeicesArray[1];
  1422. } else { $fNumber = '';}
  1423. // *** Resolve ExposureProgram
  1424. if (isset($exifData['ExposureProgram'])) { $ep = $exifData['ExposureProgram']; }
  1425. if (isset($ep)) { $ep = $this->resolveExposureProgram($ep); }
  1426. // *** Resolve MeteringMode
  1427. $mm = $exifData['MeteringMode'];
  1428. $mm = $this->resolveMeteringMode($mm);
  1429. // *** Resolve Flash
  1430. $flash = $exifData['Flash'];
  1431. $flash = $this->resolveFlash($flash);
  1432. if (isset($exifData['Make'])) {
  1433. $exifDataArray['make'] = $exifData['Make'];
  1434. } else { $exifDataArray['make'] = ''; }
  1435. if (isset($exifData['Model'])) {
  1436. $exifDataArray['model'] = $exifData['Model'];
  1437. } else { $exifDataArray['model'] = ''; }
  1438. if (isset($exifData['DateTime'])) {
  1439. $exifDataArray['date'] = $exifData['DateTime'];
  1440. } else { $exifDataArray['date'] = ''; }
  1441. if (isset($exifData['ExposureTime'])) {
  1442. $exifDataArray['exposure time'] = $exifData['ExposureTime'] . ' sec.';
  1443. } else { $exifDataArray['exposure time'] = ''; }
  1444. if ($apertureValue != '') {
  1445. $exifDataArray['aperture value'] = $apertureValue;
  1446. } else { $exifDataArray['aperture value'] = ''; }
  1447. if (isset($exifData['COMPUTED']['ApertureFNumber'])) {
  1448. $exifDataArray['f-stop'] = $exifData['COMPUTED']['ApertureFNumber'];
  1449. } else { $exifDataArray['f-stop'] = ''; }
  1450. if (isset($exifData['FNumber'])) {
  1451. $exifDataArray['fnumber'] = $exifData['FNumber'];
  1452. } else { $exifDataArray['fnumber'] = ''; }
  1453. if ($fNumber != '') {
  1454. $exifDataArray['fnumber value'] = $fNumber;
  1455. } else { $exifDataArray['fnumber value'] = ''; }
  1456. if (isset($exifData['ISOSpeedRatings'])) {
  1457. $exifDataArray['iso'] = $exifData['ISOSpeedRatings'];
  1458. } else { $exifDataArray['iso'] = ''; }
  1459. if ($focalLength != '') {
  1460. $exifDataArray['focal length'] = $focalLength;
  1461. } else { $exifDataArray['focal length'] = ''; }
  1462. if (isset($ep)) {
  1463. $exifDataArray['exposure program'] = $ep;
  1464. } else { $exifDataArray['exposure program'] = ''; }
  1465. if ($mm != '') {
  1466. $exifDataArray['metering mode'] = $mm;
  1467. } else { $exifDataArray['metering mode'] = ''; }
  1468. if ($flash != '') {
  1469. $exifDataArray['flash status'] = $flash;
  1470. } else { $exifDataArray['flash status'] = ''; }
  1471. if (isset($exifData['Artist'])) {
  1472. $exifDataArray['creator'] = $exifData['Artist'] ;
  1473. } else { $exifDataArray['creator'] = ''; }
  1474. if (isset($exifData['Copyright'])) {
  1475. $exifDataArray['copyright'] = $exifData['Copyright'];
  1476. } else { $exifDataArray['copyright'] = ''; }
  1477. // *** Orientation
  1478. if (isset($exifData['Orientation'])) {
  1479. $exifDataArray['orientation'] = $exifData['Orientation'];
  1480. } else { $exifDataArray['orientation'] = ''; }
  1481. return $exifDataArray;
  1482. }
  1483. ## --------------------------------------------------------
  1484. private function resolveExposureProgram($ep)
  1485. {
  1486. switch ($ep) {
  1487. case 0:
  1488. $ep = '';
  1489. break;
  1490. case 1:
  1491. $ep = 'manual';
  1492. break;
  1493. case 2:
  1494. $ep = 'normal program';
  1495. break;
  1496. case 3:
  1497. $ep = 'aperture priority';
  1498. break;
  1499. case 4:
  1500. $ep = 'shutter priority';
  1501. break;
  1502. case 5:
  1503. $ep = 'creative program';
  1504. break;
  1505. case 6:
  1506. $ep = 'action program';
  1507. break;
  1508. case 7:
  1509. $ep = 'portrait mode';
  1510. break;
  1511. case 8:
  1512. $ep = 'landscape mode';
  1513. break;
  1514. default:
  1515. break;
  1516. }
  1517. return $ep;
  1518. }
  1519. ## --------------------------------------------------------
  1520. private function resolveMeteringMode($mm)
  1521. {
  1522. switch ($mm) {
  1523. case 0:
  1524. $mm = 'unknown';
  1525. break;
  1526. case 1:
  1527. $mm = 'average';
  1528. break;
  1529. case 2:
  1530. $mm = 'center weighted average';
  1531. break;
  1532. case 3:
  1533. $mm = 'spot';
  1534. break;
  1535. case 4:
  1536. $mm = 'multi spot';
  1537. break;
  1538. case 5:
  1539. $mm = 'pattern';
  1540. break;
  1541. case 6:
  1542. $mm = 'partial';
  1543. break;
  1544. case 255:
  1545. $mm = 'other';
  1546. break;
  1547. default:
  1548. break;
  1549. }
  1550. return $mm;
  1551. }
  1552. ## --------------------------------------------------------
  1553. private function resolveFlash($flash)
  1554. {
  1555. switch ($flash) {
  1556. case 0:
  1557. $flash = 'flash did not fire';
  1558. break;
  1559. case 1:
  1560. $flash = 'flash fired';
  1561. break;
  1562. case 5:
  1563. $flash = 'strobe return light not detected';
  1564. break;
  1565. case 7:
  1566. $flash = 'strobe return light detected';
  1567. break;
  1568. case 9:
  1569. $flash = 'flash fired, compulsory flash mode';
  1570. break;
  1571. case 13:
  1572. $flash = 'flash fired, compulsory flash mode, return light not detected';
  1573. break;
  1574. case 15:
  1575. $flash = 'flash fired, compulsory flash mode, return light detected';
  1576. break;
  1577. case 16:
  1578. $flash = 'flash did not fire, compulsory flash mode';
  1579. break;
  1580. case 24:
  1581. $flash = 'flash did not fire, auto mode';
  1582. break;
  1583. case 25:
  1584. $flash = 'flash fired, auto mode';
  1585. break;
  1586. case 29:
  1587. $flash = 'flash fired, auto mode, return light not detected';
  1588. break;
  1589. case 31:
  1590. $flash = 'flash fired, auto mode, return light detected';
  1591. break;
  1592. case 32:
  1593. $flash = 'no flash function';
  1594. break;
  1595. case 65:
  1596. $flash = 'flash fired, red-eye reduction mode';
  1597. break;
  1598. case 69:
  1599. $flash = 'flash fired, red-eye reduction mode, return light not detected';
  1600. break;
  1601. case 71:
  1602. $flash = 'flash fired, red-eye reduction mode, return light detected';
  1603. break;
  1604. case 73:
  1605. $flash = 'flash fired, compulsory flash mode, red-eye reduction mode';
  1606. break;
  1607. case 77:
  1608. $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
  1609. break;
  1610. case 79:
  1611. $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
  1612. break;
  1613. case 89:
  1614. $flash = 'flash fired, auto mode, red-eye reduction mode';
  1615. break;
  1616. case 93:
  1617. $flash = 'flash fired, auto mode, return light not detected, red-eye reduction mode';
  1618. break;
  1619. case 95:
  1620. $flash = 'flash fired, auto mode, return light detected, red-eye reduction mode';
  1621. break;
  1622. default:
  1623. break;
  1624. }
  1625. return $flash;
  1626. }
  1627. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1628. Get IPTC Data
  1629. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1630. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1631. Write IPTC Data
  1632. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1633. public function writeIPTCcaption($value)
  1634. # Caption
  1635. {
  1636. $this->writeIPTC(120, $value);
  1637. }
  1638. ## --------------------------------------------------------
  1639. public function writeIPTCwriter($value)
  1640. {
  1641. //$this->writeIPTC(65, $value);
  1642. }
  1643. ## --------------------------------------------------------
  1644. private function writeIPTC($dat, $value)
  1645. {
  1646. # LIMIT TO JPG
  1647. $caption_block = $this->iptc_maketag(2, $dat, $value);
  1648. $image_string = iptcembed($caption_block, $this->fileName);
  1649. file_put_contents('iptc.jpg', $image_string);
  1650. }
  1651. ## --------------------------------------------------------
  1652. private function iptc_maketag($rec,$dat,$val)
  1653. # Author: Thies C. Arntzen
  1654. # Purpose: Function to format the new IPTC text
  1655. # Param in: $rec: Application record. (Were working with #2)
  1656. # $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM
  1657. # specification:
  1658. # http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
  1659. # $val: Value/data/text. Make sure this is within the length
  1660. # constraints of the IPTC IIM specification
  1661. # Ref: http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/
  1662. # http://php.net/manual/en/function.iptcembed.php
  1663. #
  1664. {
  1665. $len = strlen($val);
  1666. if ($len < 0x8000)
  1667. return chr(0x1c).chr($rec).chr($dat).
  1668. chr($len >> 8).
  1669. chr($len & 0xff).
  1670. $val;
  1671. else
  1672. return chr(0x1c).chr($rec).chr($dat).
  1673. chr(0x80).chr(0x04).
  1674. chr(($len >> 24) & 0xff).
  1675. chr(($len >> 16) & 0xff).
  1676. chr(($len >> 8 ) & 0xff).
  1677. chr(($len ) & 0xff).
  1678. $val;
  1679. }
  1680. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1681. Write XMP Data
  1682. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1683. //http://xmpphptoolkit.sourceforge.net/
  1684. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1685. Add Text
  1686. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1687. public function addText($text, $pos = '20x20', $padding = 0, $fontColor='#fff', $fontSize = 12, $angle = 0, $font = null)
  1688. # Author: Jarrod Oberto
  1689. # Date: 18-11-09
  1690. # Purpose: Add text to an image
  1691. # Param in:
  1692. # Param out:
  1693. # Reference: http://php.net/manual/en/function.imagettftext.php
  1694. # Notes: Make sure you supply the font.
  1695. #
  1696. {
  1697. // *** Convert color
  1698. $rgbArray = $this->formatColor($fontColor);
  1699. $r = $rgbArray['r'];
  1700. $g = $rgbArray['g'];
  1701. $b = $rgbArray['b'];
  1702. // *** Get text font
  1703. $font = $this->getTextFont($font);
  1704. // *** Get text size
  1705. $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
  1706. $textWidth = $textSizeArray['width'];
  1707. $textHeight = $textSizeArray['height'];
  1708. // *** Find co-ords to place text
  1709. $posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, false);
  1710. $x = $posArray['width'];
  1711. $y = $posArray['height'];
  1712. $fontColor = imagecolorallocate($this->imageResized, $r, $g, $b);
  1713. // *** Add text
  1714. imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, $text);
  1715. }
  1716. ## --------------------------------------------------------
  1717. private function getTextFont($font)
  1718. {
  1719. // *** Font path (shou
  1720. $fontPath = dirname(__FILE__) . '/' . $this->fontDir;
  1721. // *** The below is/may be needed depending on your version (see ref)
  1722. putenv('GDFONTPATH=' . realpath('.'));
  1723. // *** Check if the passed in font exsits...
  1724. if ($font == null || !file_exists($font)) {
  1725. // *** ...If not, default to this font.
  1726. $font = $fontPath . '/arimo.ttf';
  1727. // *** Check our default font exists...
  1728. if (!file_exists($font)) {
  1729. // *** If not, return false
  1730. if ($this->debug) { throw new Exception('Font not found'); }else{ return false; }
  1731. }
  1732. }
  1733. return $font;
  1734. }
  1735. ## --------------------------------------------------------
  1736. private function getTextSize($fontSize, $angle, $font, $text)
  1737. {
  1738. // *** Define box (so we can get the width)
  1739. $box = @imageTTFBbox($fontSize, $angle, $font, $text);
  1740. // *** Get width of text from dimensions
  1741. $textWidth = abs($box[4] - $box[0]);
  1742. // *** Get height of text from dimensions (should also be same as $fontSize)
  1743. $textHeight = abs($box[5] - $box[1]);
  1744. return array('height' => $textHeight, 'width' => $textWidth);
  1745. }
  1746. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1747. Add Watermark
  1748. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  1749. public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0)
  1750. # Author: Jarrod Oberto
  1751. # Date: 18-11-09
  1752. # Purpose: Add watermark image
  1753. # Param in: (str) $watermark: The watermark image
  1754. # (str) $pos: Could be a pre-determined position such as:
  1755. # tl = top left,
  1756. # t = top (middle),
  1757. # tr = top right,
  1758. # l = left,
  1759. # m = middle,
  1760. # r = right,
  1761. # bl = bottom left,
  1762. # b = bottom (middle),
  1763. # br = bottom right
  1764. # Or, it could be a co-ordinate position such as: 50x100
  1765. #
  1766. # (int) $padding: If using a pre-determined position you can
  1767. # adjust the padding from the edges by passing an amount
  1768. # in pixels. If using co-ordinates, this value is ignored.
  1769. # Param out:
  1770. # Reference: http://www.php.net/manual/en/image.examples-watermark.php
  1771. # Notes: Based on example in reference.
  1772. #
  1773. #
  1774. {
  1775. // Load the stamp and the photo to apply the watermark to
  1776. $stamp = $this->openImage ($watermarkImage); # stamp
  1777. $im = $this->imageResized; # photo
  1778. // *** Get stamps width and height
  1779. $sx = imagesx($stamp);
  1780. $sy = imagesy($stamp);
  1781. // *** Find co-ords to place image
  1782. $posArray = $this->calculatePosition($pos, $padding, $sx, $sy);
  1783. $x = $posArray['width'];
  1784. $y = $posArray['height'];
  1785. // *** Set watermark opacity
  1786. if (fix_strtolower(strrchr($watermarkImage, '.')) == '.png') {
  1787. $opacity = $this->invertTransparency($opacity, 100);
  1788. $this->filterOpacity($stamp, $opacity);
  1789. }
  1790. // Copy the watermark image onto our photo
  1791. imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp));
  1792. }
  1793. ## --------------------------------------------------------
  1794. private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = true)
  1795. #
  1796. # Author: Jarrod Oberto
  1797. # Date: 08-05-11
  1798. # Purpose: Calculate the x, y pixel cordinates of the asset to place
  1799. # Params in: (str) $pos: Either something like: "tl", "l", "br" or an
  1800. # exact position like: "100x50"
  1801. # (int) $padding: The amount of padding from the edge. Only
  1802. # used for the predefined $pos.
  1803. # (int) $assetWidth: The width of the asset to add to the image
  1804. # (int) $assetHeight: The height of the asset to add to the image
  1805. # (bol) $upperLeft: if true, the asset will be positioned based
  1806. # on the upper left x, y coords. If false, it means you're
  1807. # using the lower left as the basepoint and this will
  1808. # convert it to the upper left position
  1809. # Params out:
  1810. # NOTE: this is done from the UPPER left corner!! But will convert lower
  1811. # left basepoints to upper left if $upperleft is set to false
  1812. #
  1813. #
  1814. {
  1815. $pos = fix_strtolower($pos);
  1816. // *** If co-ords have been entered
  1817. if (strstr($pos, 'x')) {
  1818. $pos = str_replace(' ', '', $pos);
  1819. $xyArray = explode('x', $pos);
  1820. list($width, $height) = $xyArray;
  1821. } else {
  1822. switch ($pos) {
  1823. case 'tl':
  1824. $width = 0 + $padding;
  1825. $height = 0 + $padding;
  1826. break;
  1827. case 't':
  1828. $width = ($this->width / 2) - ($assetWidth / 2);
  1829. $height = 0 + $padding;
  1830. break;
  1831. case 'tr':
  1832. $width = $this->width - $assetWidth - $padding;
  1833. $height = 0 + $padding;;
  1834. break;
  1835. case 'l':
  1836. $width = 0 + $padding;
  1837. $height = ($this->height / 2) - ($assetHeight / 2);
  1838. break;
  1839. case 'm':
  1840. $width = ($this->width / 2) - ($assetWidth / 2);
  1841. $height = ($this->height / 2) - ($assetHeight / 2);
  1842. break;
  1843. case 'r':
  1844. $width = $this->width - $assetWidth - $padding;
  1845. $height = ($this->height / 2) - ($assetHeight / 2);
  1846. break;
  1847. case 'bl':
  1848. $width = 0 + $padding;
  1849. $height = $this->height - $assetHeight - $padding;
  1850. break;
  1851. case 'b':
  1852. $width = ($this->width / 2) - ($assetWidth / 2);
  1853. $height = $this->height - $assetHeight - $padding;
  1854. break;
  1855. case 'br':
  1856. $width = $this->width - $assetWidth - $padding;
  1857. $height = $this->height - $assetHeight - $padding;
  1858. break;
  1859. default:
  1860. $width = 0;
  1861. $height = 0;
  1862. break;
  1863. }
  1864. }
  1865. if (!$upperLeft) {
  1866. $height = $height + $assetHeight;
  1867. }
  1868. return array('width' => $width, 'height' => $height);
  1869. }
  1870. ## --------------------------------------------------------
  1871. private function filterOpacity(&$img, $opacity = 75)
  1872. #
  1873. # Author: aiden dot mail at freemail dot hu
  1874. # Author date: 29-03-08 08:16
  1875. # Date added: 08-05-11
  1876. # Purpose: Change opacity of image
  1877. # Params in: $img: Image resource id
  1878. # (int) $opacity: the opacity amount: 0-100, 100 being not opaque.
  1879. # Params out: (bool) true on success, else false
  1880. # Ref: http://www.php.net/manual/en/function.imagefilter.php#82162
  1881. # Notes: png only
  1882. #
  1883. {
  1884. if (!isset($opacity)) {
  1885. return false;
  1886. }
  1887. if ($opacity == 100) {
  1888. return true;
  1889. }
  1890. $opacity /= 100;
  1891. //get image width and height
  1892. $w = imagesx($img);
  1893. $h = imagesy($img);
  1894. //turn alpha blending off
  1895. imagealphablending($img, false);
  1896. //find the most opaque pixel in the image (the one with the smallest alpha value)
  1897. $minalpha = 127;
  1898. for ($x = 0; $x < $w; $x++)
  1899. for ($y = 0; $y < $h; $y++) {
  1900. $alpha = ( imagecolorat($img, $x, $y) >> 24 ) & 0xFF;
  1901. if ($alpha < $minalpha) {
  1902. $minalpha = $alpha;
  1903. }
  1904. }
  1905. //loop through image pixels and modify alpha for each
  1906. for ($x = 0; $x < $w; $x++) {
  1907. for ($y = 0; $y < $h; $y++) {
  1908. //get current alpha value (represents the TANSPARENCY!)
  1909. $colorxy = imagecolorat($img, $x, $y);
  1910. $alpha = ( $colorxy >> 24 ) & 0xFF;
  1911. //calculate new alpha
  1912. if ($minalpha !== 127) {
  1913. $alpha = 127 + 127 * $opacity * ( $alpha - 127 ) / ( 127 - $minalpha );
  1914. } else {
  1915. $alpha += 127 * $opacity;
  1916. }
  1917. //get the color index with new alpha
  1918. $alphacolorxy = imagecolorallocatealpha($img, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha);
  1919. //set pixel with the new color + opacity
  1920. if (!imagesetpixel($img, $x, $y, $alphacolorxy)) {
  1921. return false;
  1922. }
  1923. }
  1924. }
  1925. return true;
  1926. }
  1927. ## --------------------------------------------------------
  1928. private function openImage($file)
  1929. # Author: Jarrod Oberto
  1930. # Date: 27-02-08
  1931. # Purpose:
  1932. # Param in:
  1933. # Param out: n/a
  1934. # Reference:
  1935. # Notes:
  1936. #
  1937. {
  1938. if (!file_exists($file) && !$this->checkStringStartsWith('http://', $file)) { if ($this->debug) { throw new Exception('Image not found.'); }else{ throw new Exception(); }};
  1939. // *** Get extension
  1940. $extension = strrchr($file, '.');
  1941. $extension = fix_strtolower($extension);
  1942. switch($extension)
  1943. {
  1944. case '.jpg':
  1945. case '.jpeg':
  1946. $img = @imagecreatefromjpeg($file);
  1947. break;
  1948. case '.gif':
  1949. $img = @imagecreatefromgif($file);
  1950. break;
  1951. case '.png':
  1952. $img = @imagecreatefrompng($file);
  1953. break;
  1954. case '.bmp':
  1955. $img = @$this->imagecreatefrombmp($file);
  1956. break;
  1957. case '.psd':
  1958. $img = @$this->imagecreatefrompsd($file);
  1959. break;
  1960. // ... etc
  1961. default:
  1962. $img = false;
  1963. break;
  1964. }
  1965. return $img;
  1966. }
  1967. ## --------------------------------------------------------
  1968. public function reset()
  1969. #
  1970. # Author: Jarrod Oberto
  1971. # Date: 30-08-11
  1972. # Purpose: Reset the resource (allow further editing)
  1973. # Params in:
  1974. # Params out:
  1975. # Notes:
  1976. #
  1977. {
  1978. $this->__construct($this->fileName);
  1979. }
  1980. ## --------------------------------------------------------
  1981. public function saveImage($savePath, $imageQuality="100")
  1982. # Author: Jarrod Oberto
  1983. # Date: 27-02-08
  1984. # Purpose: Saves the image
  1985. # Param in: $savePath: Where to save the image including filename:
  1986. # $imageQuality: image quality you want the image saved at 0-100
  1987. # Param out: n/a
  1988. # Reference:
  1989. # Notes: * gif doesn't have a quality parameter
  1990. # * jpg has a quality setting 0-100 (100 being the best)
  1991. # * png has a quality setting 0-9 (0 being the best)
  1992. #
  1993. # * bmp files have no native support for bmp files. We use a
  1994. # third party class to save as bmp.
  1995. {
  1996. // *** Perform a check or two.
  1997. if (!is_resource($this->imageResized)) { if ($this->debug) { throw new Exception('saveImage: This is not a resource.'); }else{ throw new Exception(); }}
  1998. $fileInfoArray = pathInfo($savePath);
  1999. clearstatcache();
  2000. if (!is_writable($fileInfoArray['dirname'])) { if ($this->debug) { throw new Exception('The path is not writable. Please check your permissions.'); }else{ throw new Exception(); }}
  2001. // *** Get extension
  2002. $extension = strrchr($savePath, '.');
  2003. $extension = fix_strtolower($extension);
  2004. $error = '';
  2005. switch($extension)
  2006. {
  2007. case '.jpg':
  2008. case '.jpeg':
  2009. $this->checkInterlaceImage($this->isInterlace);
  2010. if (imagetypes() & IMG_JPG) {
  2011. imagejpeg($this->imageResized, $savePath, $imageQuality);
  2012. } else { $error = 'jpg'; }
  2013. break;
  2014. case '.gif':
  2015. $this->checkInterlaceImage($this->isInterlace);
  2016. if (imagetypes() & IMG_GIF) {
  2017. imagegif($this->imageResized, $savePath);
  2018. } else { $error = 'gif'; }
  2019. break;
  2020. case '.png':
  2021. // *** Scale quality from 0-100 to 0-9
  2022. $scaleQuality = round(($imageQuality/100) * 9);
  2023. // *** Invert qualit setting as 0 is best, not 9
  2024. $invertScaleQuality = 9 - $scaleQuality;
  2025. $this->checkInterlaceImage($this->isInterlace);
  2026. if (imagetypes() & IMG_PNG) {
  2027. imagepng($this->imageResized, $savePath, $invertScaleQuality);
  2028. } else { $error = 'png'; }
  2029. break;
  2030. case '.bmp':
  2031. file_put_contents($savePath, $this->GD2BMPstring($this->imageResized));
  2032. break;
  2033. // ... etc
  2034. default:
  2035. // *** No extension - No save.
  2036. $this->errorArray[] = 'This file type (' . $extension . ') is not supported. File not saved.';
  2037. break;
  2038. }
  2039. //imagedestroy($this->imageResized);
  2040. // *** Display error if a file type is not supported.
  2041. if ($error != '') {
  2042. $this->errorArray[] = $error . ' support is NOT enabled. File not saved.';
  2043. }
  2044. }
  2045. ## --------------------------------------------------------
  2046. public function displayImage($fileType = 'jpg', $imageQuality="100")
  2047. # Author: Jarrod Oberto
  2048. # Date: 18-11-09
  2049. # Purpose: Display images directly to the browser
  2050. # Param in: The image type you want to display
  2051. # Param out:
  2052. # Reference:
  2053. # Notes:
  2054. #
  2055. {
  2056. if (!is_resource($this->imageResized)) { if ($this->debug) { throw new Exception('saveImage: This is not a resource.'); }else{ throw new Exception(); }}
  2057. switch($fileType)
  2058. {
  2059. case 'jpg':
  2060. case 'jpeg':
  2061. header('Content-type: image/jpeg');
  2062. imagejpeg($this->imageResized, '', $imageQuality);
  2063. break;
  2064. case 'gif':
  2065. header('Content-type: image/gif');
  2066. imagegif($this->imageResized);
  2067. break;
  2068. case 'png':
  2069. header('Content-type: image/png');
  2070. // *** Scale quality from 0-100 to 0-9
  2071. $scaleQuality = round(($imageQuality/100) * 9);
  2072. // *** Invert qualit setting as 0 is best, not 9
  2073. $invertScaleQuality = 9 - $scaleQuality;
  2074. imagepng($this->imageResized, '', $invertScaleQuality);
  2075. break;
  2076. case 'bmp':
  2077. echo 'bmp file format is not supported.';
  2078. break;
  2079. // ... etc
  2080. default:
  2081. // *** No extension - No save.
  2082. break;
  2083. }
  2084. //imagedestroy($this->imageResized);
  2085. }
  2086. ## --------------------------------------------------------
  2087. public function setTransparency($bool)
  2088. # Sep 2011
  2089. {
  2090. $this->keepTransparency = $bool;
  2091. }
  2092. ## --------------------------------------------------------
  2093. public function setFillColor($value)
  2094. # Sep 2011
  2095. # Param in: (mixed) $value: (array) Could be an array of RGB
  2096. # (str) Could be hex #ffffff or #fff, fff, ffffff
  2097. #
  2098. # If the keepTransparency is set to false, then no transparency is to be used.
  2099. # This is ideal when you want to save as jpg.
  2100. #
  2101. # this method allows you to set the background color to use instead of
  2102. # transparency.
  2103. #
  2104. {
  2105. $colorArray = $this->formatColor($value);
  2106. $this->fillColorArray = $colorArray;
  2107. }
  2108. ## --------------------------------------------------------
  2109. public function setCropFromTop($value)
  2110. # Sep 2011
  2111. {
  2112. $this->cropFromTopPercent = $value;
  2113. }
  2114. ## --------------------------------------------------------
  2115. public function testGDInstalled()
  2116. # Author: Jarrod Oberto
  2117. # Date: 27-02-08
  2118. # Purpose: Test to see if GD is installed
  2119. # Param in: n/a
  2120. # Param out: (bool) True is gd extension loaded otherwise false
  2121. # Reference:
  2122. # Notes:
  2123. #
  2124. {
  2125. if(extension_loaded('gd') && function_exists('gd_info'))
  2126. {
  2127. $gdInstalled = true;
  2128. }
  2129. else
  2130. {
  2131. $gdInstalled = false;
  2132. }
  2133. return $gdInstalled;
  2134. }
  2135. ## --------------------------------------------------------
  2136. public function testEXIFInstalled()
  2137. # Author: Jarrod Oberto
  2138. # Date: 08-05-11
  2139. # Purpose: Test to see if EXIF is installed
  2140. # Param in: n/a
  2141. # Param out: (bool) True is exif extension loaded otherwise false
  2142. # Reference:
  2143. # Notes:
  2144. #
  2145. {
  2146. if(extension_loaded('exif'))
  2147. {
  2148. $exifInstalled = true;
  2149. }
  2150. else
  2151. {
  2152. $exifInstalled = false;
  2153. }
  2154. return $exifInstalled;
  2155. }
  2156. ## --------------------------------------------------------
  2157. public function testIsImage($image)
  2158. # Author: Jarrod Oberto
  2159. # Date: 27-02-08
  2160. # Purpose: Test if file is an image
  2161. # Param in: n/a
  2162. # Param out: n/a
  2163. # Reference:
  2164. # Notes:
  2165. #
  2166. {
  2167. if ($image)
  2168. {
  2169. $fileIsImage = true;
  2170. }
  2171. else
  2172. {
  2173. $fileIsImage = false;
  2174. }
  2175. return $fileIsImage;
  2176. }
  2177. ## --------------------------------------------------------
  2178. public function testFunct()
  2179. # Author: Jarrod Oberto
  2180. # Date: 27-02-08
  2181. # Purpose: Test Function
  2182. # Param in: n/a
  2183. # Param out: n/a
  2184. # Reference:
  2185. # Notes:
  2186. #
  2187. {
  2188. echo $this->height;
  2189. }
  2190. ## --------------------------------------------------------
  2191. public function setForceStretch($value)
  2192. # Author: Jarrod Oberto
  2193. # Date: 23-12-10
  2194. # Purpose:
  2195. # Param in: (bool) $value
  2196. # Param out: n/a
  2197. # Reference:
  2198. # Notes:
  2199. #
  2200. {
  2201. $this->forceStretch = $value;
  2202. }
  2203. ## --------------------------------------------------------
  2204. public function setFile($fileName)
  2205. # Author: Jarrod Oberto
  2206. # Date: 28-02-08
  2207. # Purpose:
  2208. # Param in: n/a
  2209. # Param out: n/a
  2210. # Reference:
  2211. # Notes:
  2212. #
  2213. {
  2214. self::__construct($fileName);
  2215. }
  2216. ## --------------------------------------------------------
  2217. public function getFileName()
  2218. # Author: Jarrod Oberto
  2219. # Date: 10-09-08
  2220. # Purpose:
  2221. # Param in: n/a
  2222. # Param out: n/a
  2223. # Reference:
  2224. # Notes:
  2225. #
  2226. {
  2227. return $this->fileName;
  2228. }
  2229. ## --------------------------------------------------------
  2230. public function getHeight()
  2231. {
  2232. return $this->height;
  2233. }
  2234. ## --------------------------------------------------------
  2235. public function getWidth()
  2236. {
  2237. return $this->width;
  2238. }
  2239. ## --------------------------------------------------------
  2240. public function getOriginalHeight()
  2241. {
  2242. return $this->heightOriginal;
  2243. }
  2244. ## --------------------------------------------------------
  2245. public function getOriginalWidth()
  2246. {
  2247. return $this->widthOriginal;
  2248. }
  2249. ## --------------------------------------------------------
  2250. public function getErrors()
  2251. # Author: Jarrod Oberto
  2252. # Date: 19-11-09
  2253. # Purpose: Returns the error array
  2254. # Param in: n/a
  2255. # Param out: Array of errors
  2256. # Reference:
  2257. # Notes:
  2258. #
  2259. {
  2260. return $this->errorArray;
  2261. }
  2262. ## --------------------------------------------------------
  2263. private function checkInterlaceImage($isEnabled)
  2264. # jpg will use progressive (they don't use interace)
  2265. {
  2266. if ($isEnabled) {
  2267. imageinterlace($this->imageResized, $isEnabled);
  2268. }
  2269. }
  2270. ## --------------------------------------------------------
  2271. protected function formatColor($value)
  2272. # Author: Jarrod Oberto
  2273. # Date: 09-05-11
  2274. # Purpose: Determine color method passed in and return color as RGB
  2275. # Param in: (mixed) $value: (array) Could be an array of RGB
  2276. # (str) Could be hex #ffffff or #fff, fff, ffffff
  2277. # Param out:
  2278. # Reference:
  2279. # Notes:
  2280. #
  2281. {
  2282. $rgbArray = array();
  2283. // *** If it's an array it should be R, G, B
  2284. if (is_array($value)) {
  2285. if (key($value) == 0 && count($value) == 3) {
  2286. $rgbArray['r'] = $value[0];
  2287. $rgbArray['g'] = $value[1];
  2288. $rgbArray['b'] = $value[2];
  2289. } else {
  2290. $rgbArray = $value;
  2291. }
  2292. } else if (fix_strtolower($value) == 'transparent') {
  2293. $rgbArray = array(
  2294. 'r' => 255,
  2295. 'g' => 255,
  2296. 'b' => 255,
  2297. 'a' => 127
  2298. );
  2299. } else {
  2300. // *** ...Else it should be hex. Let's make it RGB
  2301. $rgbArray = $this -> hex2dec($value);
  2302. }
  2303. return $rgbArray;
  2304. }
  2305. ## --------------------------------------------------------
  2306. function hex2dec($hex)
  2307. # Purpose: Convert #hex color to RGB
  2308. {
  2309. $color = str_replace('#', '', $hex);
  2310. if (strlen($color) == 3) {
  2311. $color = $color . $color;
  2312. }
  2313. $rgb = array(
  2314. 'r' => hexdec(substr($color, 0, 2)),
  2315. 'g' => hexdec(substr($color, 2, 2)),
  2316. 'b' => hexdec(substr($color, 4, 2)),
  2317. 'a' => 0
  2318. );
  2319. return $rgb;
  2320. }
  2321. ## --------------------------------------------------------
  2322. private function createImageColor ($colorArray)
  2323. {
  2324. $r = $colorArray['r'];
  2325. $g = $colorArray['g'];
  2326. $b = $colorArray['b'];
  2327. return imagecolorallocate($this->imageResized, $r, $g, $b);
  2328. }
  2329. ## --------------------------------------------------------
  2330. private function testColorExists($colorArray)
  2331. {
  2332. $r = $colorArray['r'];
  2333. $g = $colorArray['g'];
  2334. $b = $colorArray['b'];
  2335. if (imagecolorexact($this->imageResized, $r, $g, $b) == -1) {
  2336. return false;
  2337. } else {
  2338. return true;
  2339. }
  2340. }
  2341. ## --------------------------------------------------------
  2342. private function findUnusedGreen()
  2343. # Purpose: We find a green color suitable to use like green-screen effect.
  2344. # Therefore, the color must not exist in the image.
  2345. {
  2346. $green = 255;
  2347. do {
  2348. $greenChroma = array(0, $green, 0);
  2349. $colorArray = $this->formatColor($greenChroma);
  2350. $match = $this->testColorExists($colorArray);
  2351. $green--;
  2352. } while ($match == false && $green > 0);
  2353. // *** If no match, just bite the bullet and use green value of 255
  2354. if (!$match) {
  2355. $greenChroma = array(0, $green, 0);
  2356. }
  2357. return $greenChroma;
  2358. }
  2359. ## --------------------------------------------------------
  2360. private function findUnusedBlue()
  2361. # Purpose: We find a green color suitable to use like green-screen effect.
  2362. # Therefore, the color must not exist in the image.
  2363. {
  2364. $blue = 255;
  2365. do {
  2366. $blueChroma = array(0, 0, $blue);
  2367. $colorArray = $this->formatColor($blueChroma);
  2368. $match = $this->testColorExists($colorArray);
  2369. $blue--;
  2370. } while ($match == false && $blue > 0);
  2371. // *** If no match, just bite the bullet and use blue value of 255
  2372. if (!$match) {
  2373. $blueChroma = array(0, 0, $blue);
  2374. }
  2375. return $blueChroma;
  2376. }
  2377. ## --------------------------------------------------------
  2378. private function invertTransparency($value, $originalMax, $invert=true)
  2379. # Purpose: This does two things:
  2380. # 1) Convert the range from 0-127 to 0-100
  2381. # 2) Inverts value to 100 is not transparent while 0 is fully
  2382. # transparent (like Photoshop)
  2383. {
  2384. // *** Test max range
  2385. if ($value > $originalMax) {
  2386. $value = $originalMax;
  2387. }
  2388. // *** Test min range
  2389. if ($value < 0) {
  2390. $value = 0;
  2391. }
  2392. if ($invert) {
  2393. return $originalMax - (($value/100) * $originalMax);
  2394. } else {
  2395. return ($value/100) * $originalMax;
  2396. }
  2397. }
  2398. ## --------------------------------------------------------
  2399. private function transparentImage($src)
  2400. {
  2401. // *** making images with white bg transparent
  2402. $r1 = 0;
  2403. $g1 = 255;
  2404. $b1 = 0;
  2405. for ($x = 0; $x < imagesx($src); ++$x) {
  2406. for ($y = 0; $y < imagesy($src); ++$y) {
  2407. $color = imagecolorat($src, $x, $y);
  2408. $r = ($color >> 16) & 0xFF;
  2409. $g = ($color >> 8) & 0xFF;
  2410. $b = $color & 0xFF;
  2411. for ($i = 0; $i < 270; $i++) {
  2412. //if ($r . $g . $b == ($r1 + $i) . ($g1 + $i) . ($b1 + $i)) {
  2413. if ($r == 0 && $g == 255 && $b == 0) {
  2414. //if ($g == 255) {
  2415. $trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127);
  2416. imagefill($src, $x, $y, $trans_colour);
  2417. }
  2418. }
  2419. }
  2420. }
  2421. return $src;
  2422. }
  2423. ## --------------------------------------------------------
  2424. function checkStringStartsWith($needle, $haystack)
  2425. # Check if a string starts with a specific pattern
  2426. {
  2427. return (substr($haystack, 0, strlen($needle))==$needle);
  2428. }
  2429. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  2430. BMP SUPPORT (SAVING) - James Heinrich
  2431. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  2432. private function GD2BMPstring(&$gd_image)
  2433. # Author: James Heinrich
  2434. # Purpose: Save file as type bmp
  2435. # Param in: The image canvas (passed as ref)
  2436. # Param out:
  2437. # Reference:
  2438. # Notes: This code was stripped out of two external files
  2439. # (phpthumb.bmp.php,phpthumb.functions.php) and added below to
  2440. # avoid dependancies.
  2441. #
  2442. {
  2443. $imageX = ImageSX($gd_image);
  2444. $imageY = ImageSY($gd_image);
  2445. $BMP = '';
  2446. for ($y = ($imageY - 1); $y >= 0; $y--) {
  2447. $thisline = '';
  2448. for ($x = 0; $x < $imageX; $x++) {
  2449. $argb = $this->GetPixelColor($gd_image, $x, $y);
  2450. $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']);
  2451. }
  2452. while (strlen($thisline) % 4) {
  2453. $thisline .= "\x00";
  2454. }
  2455. $BMP .= $thisline;
  2456. }
  2457. $bmpSize = strlen($BMP) + 14 + 40;
  2458. // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
  2459. $BITMAPFILEHEADER = 'BM'; // WORD bfType;
  2460. $BITMAPFILEHEADER .= $this->LittleEndian2String($bmpSize, 4); // DWORD bfSize;
  2461. $BITMAPFILEHEADER .= $this->LittleEndian2String( 0, 2); // WORD bfReserved1;
  2462. $BITMAPFILEHEADER .= $this->LittleEndian2String( 0, 2); // WORD bfReserved2;
  2463. $BITMAPFILEHEADER .= $this->LittleEndian2String( 54, 4); // DWORD bfOffBits;
  2464. // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
  2465. $BITMAPINFOHEADER = $this->LittleEndian2String( 40, 4); // DWORD biSize;
  2466. $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageX, 4); // LONG biWidth;
  2467. $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageY, 4); // LONG biHeight;
  2468. $BITMAPINFOHEADER .= $this->LittleEndian2String( 1, 2); // WORD biPlanes;
  2469. $BITMAPINFOHEADER .= $this->LittleEndian2String( 24, 2); // WORD biBitCount;
  2470. $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biCompression;
  2471. $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biSizeImage;
  2472. $BITMAPINFOHEADER .= $this->LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter;
  2473. $BITMAPINFOHEADER .= $this->LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter;
  2474. $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biClrUsed;
  2475. $BITMAPINFOHEADER .= $this->LittleEndian2String( 0, 4); // DWORD biClrImportant;
  2476. return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP;
  2477. }
  2478. ## --------------------------------------------------------
  2479. private function GetPixelColor(&$img, $x, $y)
  2480. # Author: James Heinrich
  2481. # Purpose:
  2482. # Param in:
  2483. # Param out:
  2484. # Reference:
  2485. # Notes:
  2486. #
  2487. {
  2488. if (!is_resource($img)) {
  2489. return false;
  2490. }
  2491. return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
  2492. }
  2493. ## --------------------------------------------------------
  2494. private function LittleEndian2String($number, $minbytes=1)
  2495. # Author: James Heinrich
  2496. # Purpose: BMP SUPPORT (SAVING)
  2497. # Param in:
  2498. # Param out:
  2499. # Reference:
  2500. # Notes:
  2501. #
  2502. {
  2503. $intstring = '';
  2504. while ($number > 0) {
  2505. $intstring = $intstring.chr($number & 255);
  2506. $number >>= 8;
  2507. }
  2508. return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
  2509. }
  2510. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  2511. BMP SUPPORT (READING)
  2512. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  2513. private function ImageCreateFromBMP($filename)
  2514. # Author: DHKold
  2515. # Date: The 15th of June 2005
  2516. # Version: 2.0B
  2517. # Purpose: To create an image from a BMP file.
  2518. # Param in: BMP file to open.
  2519. # Param out: Return a resource like the other ImageCreateFrom functions
  2520. # Reference: http://us3.php.net/manual/en/function.imagecreate.php#53879
  2521. # Bug fix: Author: domelca at terra dot es
  2522. # Date: 06 March 2008
  2523. # Fix: Correct 16bit BMP support
  2524. # Notes:
  2525. #
  2526. {
  2527. //Ouverture du fichier en mode binaire
  2528. if (! $f1 = fopen($filename,"rb")) return FALSE;
  2529. //1 : Chargement des ent�tes FICHIER
  2530. $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
  2531. if ($FILE['file_type'] != 19778) return FALSE;
  2532. //2 : Chargement des ent�tes BMP
  2533. $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
  2534. '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
  2535. '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
  2536. $BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
  2537. if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
  2538. $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
  2539. $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
  2540. $BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
  2541. $BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
  2542. $BMP['decal'] = 4-(4*$BMP['decal']);
  2543. if ($BMP['decal'] == 4) $BMP['decal'] = 0;
  2544. //3 : Chargement des couleurs de la palette
  2545. $PALETTE = array();
  2546. if ($BMP['colors'] < 16777216)
  2547. {
  2548. $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
  2549. }
  2550. //4 : Cr�ation de l'image
  2551. $IMG = fread($f1,$BMP['size_bitmap']);
  2552. $VIDE = chr(0);
  2553. $res = imagecreatetruecolor($BMP['width'],$BMP['height']);
  2554. $P = 0;
  2555. $Y = $BMP['height']-1;
  2556. while ($Y >= 0)
  2557. {
  2558. $X=0;
  2559. while ($X < $BMP['width'])
  2560. {
  2561. if ($BMP['bits_per_pixel'] == 24)
  2562. $COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
  2563. elseif ($BMP['bits_per_pixel'] == 16)
  2564. {
  2565. /*
  2566. * BMP 16bit fix
  2567. * =================
  2568. *
  2569. * Ref: http://us3.php.net/manual/en/function.imagecreate.php#81604
  2570. *
  2571. * Notes:
  2572. * "don't work with bmp 16 bits_per_pixel. change pixel
  2573. * generator for this."
  2574. *
  2575. */
  2576. // *** Original code (don't work)
  2577. //$COLOR = unpack("n",substr($IMG,$P,2));
  2578. //$COLOR[1] = $PALETTE[$COLOR[1]+1];
  2579. $COLOR = unpack("v",substr($IMG,$P,2));
  2580. $blue = ($COLOR[1] & 0x001f) << 3;
  2581. $green = ($COLOR[1] & 0x07e0) >> 3;
  2582. $red = ($COLOR[1] & 0xf800) >> 8;
  2583. $COLOR[1] = $red * 65536 + $green * 256 + $blue;
  2584. }
  2585. elseif ($BMP['bits_per_pixel'] == 8)
  2586. {
  2587. $COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
  2588. $COLOR[1] = $PALETTE[$COLOR[1]+1];
  2589. }
  2590. elseif ($BMP['bits_per_pixel'] == 4)
  2591. {
  2592. $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
  2593. if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
  2594. $COLOR[1] = $PALETTE[$COLOR[1]+1];
  2595. }
  2596. elseif ($BMP['bits_per_pixel'] == 1)
  2597. {
  2598. $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
  2599. if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7;
  2600. elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
  2601. elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
  2602. elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
  2603. elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
  2604. elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
  2605. elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
  2606. elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
  2607. $COLOR[1] = $PALETTE[$COLOR[1]+1];
  2608. }
  2609. else
  2610. return FALSE;
  2611. imagesetpixel($res,$X,$Y,$COLOR[1]);
  2612. $X++;
  2613. $P += $BMP['bytes_per_pixel'];
  2614. }
  2615. $Y--;
  2616. $P+=$BMP['decal'];
  2617. }
  2618. //Fermeture du fichier
  2619. fclose($f1);
  2620. return $res;
  2621. }
  2622. /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
  2623. PSD SUPPORT (READING)
  2624. *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
  2625. private function imagecreatefrompsd($fileName)
  2626. # Author: Tim de Koning
  2627. # Version: 1.3
  2628. # Purpose: To create an image from a PSD file.
  2629. # Param in: PSD file to open.
  2630. # Param out: Return a resource like the other ImageCreateFrom functions
  2631. # Reference: http://www.kingsquare.nl/phppsdreader
  2632. # Notes:
  2633. #
  2634. {
  2635. if (file_exists($this->psdReaderPath)) {
  2636. include_once($this->psdReaderPath);
  2637. $psdReader = new PhpPsdReader($fileName);
  2638. if (isset($psdReader->infoArray['error'])) return '';
  2639. else return $psdReader->getImage();
  2640. } else {
  2641. return false;
  2642. }
  2643. }
  2644. ## --------------------------------------------------------
  2645. public function __destruct() {
  2646. if (is_resource($this->imageResized)) {
  2647. imagedestroy($this->imageResized);
  2648. }
  2649. }
  2650. ## --------------------------------------------------------
  2651. }
  2652. /*
  2653. * Example with some API calls (outdated):
  2654. *
  2655. *
  2656. * ===============================
  2657. * Compulsary
  2658. * ===============================
  2659. *
  2660. * include("classes/resize_class.php");
  2661. *
  2662. * // *** Initialise object
  2663. * $magicianObj = new resize('images/cars/large/a.jpg');
  2664. *
  2665. * // *** Turn off stretching (optional)
  2666. * $magicianObj -> setForceStretch(false);
  2667. *
  2668. * // *** Resize object
  2669. * $magicianObj -> resizeImage(150, 100, 0);
  2670. *
  2671. * ===============================
  2672. * Image options - can run none, one, or all.
  2673. * ===============================
  2674. *
  2675. * // *** Add watermark
  2676. * $magicianObj -> addWatermark('stamp.png');
  2677. *
  2678. * // *** Add text
  2679. * $magicianObj -> addText('testing...');
  2680. *
  2681. * ===============================
  2682. * Output options - can run one, or the other, or both.
  2683. * ===============================
  2684. *
  2685. * // *** Save image to disk
  2686. * $magicianObj -> saveImage('images/cars/large/b.jpg', 100);
  2687. *
  2688. * // *** Or output to screen (params in can be jpg, gif, png)
  2689. * $magicianObj -> displayImage('png');
  2690. *
  2691. * ===============================
  2692. * Return options - return errors. nice for debuggin.
  2693. * ===============================
  2694. *
  2695. * // *** Return error array
  2696. * $errorArray = $magicianObj -> getErrors();
  2697. *
  2698. *
  2699. * ===============================
  2700. * Cleanup options - not really neccessary, but good practice
  2701. * ===============================
  2702. *
  2703. * // *** Free used memory
  2704. * $magicianObj -> __destruct();
  2705. */
  2706. ?>