/plugins/imageGalleryFromFolder/includes/Image.class.php

https://github.com/frozeman/feindura-flat-file-cms · PHP · 372 lines · 179 code · 54 blank · 139 comment · 67 complexity · 5e90ed8834d7caee7abbd42fc6a4b6c3 MD5 · raw file

  1. <?php
  2. /**
  3. * Image - Provides an Interface to the GD-Library for image manipulation
  4. *
  5. *
  6. * @license MIT-style License
  7. * @author Christoph Pojer <christoph.pojer@gmail.com>
  8. * @author Additions: Fabian Vogelsteller <fabian.vogelsteller@gmail.com>
  9. *
  10. * @link http://www.bin-co.com/php/scripts/classes/gd_image/ Based on work by "Binny V A"
  11. *
  12. * @version 1.2
  13. * Changlog<br>
  14. * - 1.2 add documentRoot as variable to the constructor
  15. * - 1.11 fixed $ratio in resize when both values are given
  16. * - 1.1 add real resizing, with comparison of ratio
  17. * - 1.01 small fixes in process method and add set memory limit to a higher value
  18. */
  19. class Image {
  20. /**
  21. * The path to the image file
  22. *
  23. * @var string
  24. */
  25. private $file;
  26. /**
  27. * The image resource
  28. *
  29. * @var resource
  30. */
  31. private $image;
  32. /**
  33. * Metadata regarding the image
  34. *
  35. * @var array
  36. */
  37. private $meta;
  38. /**
  39. * @param string $file The path to the image file
  40. */
  41. public function __construct($file,$documentRoot = false){
  42. ini_set('memory_limit', '120M'); // handle large images
  43. $documentRoot = (!empty($documentRoot)) ? $documentRoot : $_SERVER['DOCUMENT_ROOT'];
  44. $file = str_replace('\\','/',$file);
  45. $file = preg_replace('#/+#','/',$file);
  46. $file = str_replace($documentRoot,'',$file);
  47. $file = $documentRoot.$file;
  48. $file = realpath($file);
  49. if(!file_exists($file))
  50. return;
  51. $this->file = $file;
  52. $img = getimagesize($file);
  53. /*
  54. echo basename($file)."\n";
  55. var_dump(filesize($file));
  56. $this->showMemoryUsage();
  57. echo "\n";
  58. */
  59. $this->meta = array(
  60. 'width' => $img[0],
  61. 'height' => $img[1],
  62. 'mime' => $img['mime'],
  63. 'ext' => end(explode('/', $img['mime'])),
  64. );
  65. if($this->meta['ext']=='jpg')
  66. $this->meta['ext'] = 'jpeg';
  67. if(!in_array($this->meta['ext'], array('gif', 'png', 'jpeg')))
  68. return;
  69. if(in_array($this->meta['ext'], array('gif', 'png'))){
  70. $this->image = $this->create();
  71. $fn = 'imagecreatefrom'.$this->meta['ext'];
  72. $original = $fn($file);
  73. imagecopyresampled($this->image, $original, 0, 0, 0, 0, $this->meta['width'], $this->meta['height'], $this->meta['width'], $this->meta['height']);
  74. } else {
  75. $this->image = imagecreatefromjpeg($file);
  76. }
  77. }
  78. public function __destruct(){
  79. if(!empty($this->image)) imagedestroy($this->image);
  80. unset($this->image);
  81. }
  82. /**
  83. * Returns the size of the image
  84. *
  85. * @return array
  86. */
  87. public function getSize(){
  88. return array(
  89. 'width' => $this->meta['width'],
  90. 'height' => $this->meta['height'],
  91. );
  92. }
  93. /**
  94. * Creates a new, empty image with the desired size
  95. *
  96. * @param int $x
  97. * @param int $y
  98. * @param string $ext
  99. * @return resource
  100. */
  101. private function create($x = null, $y = null, $ext = null){
  102. if(!$x) $x = $this->meta['width'];
  103. if(!$y) $y = $this->meta['height'];
  104. $image = imagecreatetruecolor($x, $y);
  105. if(!$ext) $ext = $this->meta['ext'];
  106. if($ext=='png'){
  107. imagealphablending($image, false);
  108. imagefilledrectangle($image, 0, 0, $x, $y, imagecolorallocatealpha($image, 0, 0, 0, 127));
  109. }
  110. return $image;
  111. }
  112. /**
  113. * Replaces the image resource with the given parameter
  114. *
  115. * @param resource $new
  116. */
  117. private function set($new){
  118. if(!empty($this->image)) imagedestroy($this->image);
  119. $this->image = $new;
  120. $this->meta['width'] = imagesx($this->image);
  121. $this->meta['height'] = imagesy($this->image);
  122. }
  123. /**
  124. * Returns the path to the image file
  125. *
  126. * @return string
  127. */
  128. public function getImagePath(){
  129. return $this->file;
  130. }
  131. /**
  132. * Returns the resource of the image file
  133. *
  134. * @return resource
  135. */
  136. public function getResource(){
  137. return $this->image;
  138. }
  139. /**
  140. * Rotates the image by the given angle
  141. *
  142. * @param int $angle
  143. * @param array $bgcolor An indexed array with red/green/blue/alpha values
  144. * @return Image
  145. */
  146. public function rotate($angle, $bgcolor = null){
  147. if(empty($this->image) || !$angle || $angle>=360) return $this;
  148. $this->set(imagerotate($this->image, $angle, is_array($bgcolor) ? imagecolorallocatealpha($this->image, $bgcolor[0], $bgcolor[1], $bgcolor[2], !empty($bgcolor[3]) ? $bgcolor[3] : null) : $bgcolor));
  149. return $this;
  150. }
  151. /**
  152. * Resizes the image to the given size, automatically calculates
  153. * the new ratio if parameter {@link $ratio} is set to true
  154. *
  155. * @param int $x
  156. * @param int $y
  157. * @param bool $ratio
  158. * @param bool $resizeWhenSmaller if FALSE the images will not be resized when already smaller, if TRUE the images will always be resized
  159. * @return false|resource Image resource or fals, if it couldnt be resized
  160. */
  161. public function resize($x = null, $y = null, $ratio = true, $resizeWhenSmaller = true){
  162. if(empty($this->image) || (empty($x) && empty($y))) return false;
  163. $xStart = $x;
  164. $yStart = $y;
  165. $ratioX = $this->meta['width'] / $this->meta['height'];
  166. $ratioY = $this->meta['height'] / $this->meta['width'];
  167. //echo 'ALLOWED: <br>'.$xStart.'x'."<br>".$yStart.'y'."<br>---------------<br>";
  168. // ->> keep the RATIO
  169. if($ratio) {
  170. //echo 'BEGINN: <br>'.$this->meta['width'].'x'."<br>".$this->meta['height'].'y'."<br><br>";
  171. // -> align to WIDTH
  172. if(!empty($x) && ($x < $this->meta['width'] || $resizeWhenSmaller))
  173. $y = round($x / $ratioX);
  174. // -> align to HEIGHT
  175. elseif(!empty($y) && ($y < $this->meta['height'] || $resizeWhenSmaller))
  176. $x = round($y / $ratioY);
  177. else {
  178. $y = $this->meta['height'];
  179. $x = $this->meta['width'];
  180. }
  181. //echo 'BET: <br>'.$x.'x'."<br>".$y.'y'."<br><br>";
  182. // ->> align to WIDTH AND HEIGHT
  183. if((!empty($yStart) && $y > $yStart) || (!empty($xStart) && $x > $xStart)) {
  184. if($y > $yStart) {
  185. $y = $yStart;
  186. $x = round($y / $ratioY);
  187. } elseif($x > $xStart) {
  188. $x = $xStart;
  189. $y = round($x / $ratioX);
  190. }
  191. }
  192. // ->> DONT keep the RATIO (but keep ratio when, only width OR height is set)
  193. } else {
  194. // RATIO X
  195. if(!empty($y) && empty($x) && ($y < $this->meta['height'] || $resizeWhenSmaller))
  196. $x = round($y / $ratioX);
  197. // RATIO Y
  198. elseif(empty($y) && !empty($x) && ($x < $this->meta['width'] || $resizeWhenSmaller))
  199. $y = round($x / $ratioY);
  200. }
  201. //echo 'END: <br>'.$x.'x'."<br>".$y.'y'."<br><br>";
  202. $new = $this->create($x, $y);
  203. if(imagecopyresampled($new, $this->image, 0, 0, 0, 0, $x, $y, $this->meta['width'], $this->meta['height'])) {
  204. $this->set($new);
  205. return $this;
  206. } else
  207. return false;
  208. }
  209. /**
  210. * Crops the image. The values are given like margin/padding values in css
  211. *
  212. * <b>Example</b>
  213. * <ul>
  214. * <li>crop(10) - Crops by 10px on all sides</li>
  215. * <li>crop(10, 5) - Crops by 10px on top and bottom and by 5px on left and right sides</li>
  216. * <li>crop(10, 5, 5) - Crops by 10px on top and by 5px on left, right and bottom sides</li>
  217. * <li>crop(10, 5, 3, 2) - Crops by 10px on top, 5px by right, 3px by bottom and 2px by left sides</li>
  218. * </ul>
  219. *
  220. * @param int $top
  221. * @param int $right
  222. * @param int $bottom
  223. * @param int $left
  224. * @return Image
  225. */
  226. public function crop($top, $right = null, $bottom = null, $left = null){
  227. if(empty($this->image)) return $this;
  228. if(!is_numeric($right) && !is_numeric($bottom) && !is_numeric($left))
  229. $right = $bottom = $left = $top;
  230. if(!is_numeric($bottom) && !is_numeric($left)){
  231. $bottom = $top;
  232. $left = $right;
  233. }
  234. if(!is_numeric($left))
  235. $left = $right;
  236. $x = $this->meta['width']-$left-$right;
  237. $y = $this->meta['height']-$top-$bottom;
  238. if($x<0 || $y<0) return $this;
  239. $new = $this->create($x, $y);
  240. imagecopy($new, $this->image, 0, 0, $left, $top, $x, $y);
  241. $this->set($new);
  242. return $this;
  243. }
  244. /**
  245. * Flips the image horizontally or vertically. To Flip both just use ->rotate(180)
  246. *
  247. * @see Image::rotate()
  248. * @param string $type Either horizontal or vertical
  249. * @return Image
  250. */
  251. public function flip($type){
  252. if(empty($this->image) || !in_array($type, array('horizontal', 'vertical'))) return $this;
  253. $new = $this->create();
  254. if($type=='horizontal')
  255. for($x=0;$x<$this->meta['width'];$x++)
  256. imagecopy($new, $this->image, $this->meta['width']-$x-1, 0, $x, 0, 1, $this->meta['height']);
  257. elseif($type=='vertical')
  258. for($y=0;$y<$this->meta['height'];$y++)
  259. imagecopy($new, $this->image, 0, $this->meta['height']-$y-1, 0, $y, $this->meta['width'], 1);
  260. $this->set($new);
  261. return $this;
  262. }
  263. /**
  264. * Stores the image in the desired directory or overwrite the old one
  265. *
  266. * @param string $ext
  267. * @param string $file
  268. */
  269. public function process($ext = null, $file = null){
  270. if(!empty($this->image)) {
  271. if(!$ext) $ext = $this->meta['ext'];
  272. if($ext=='jpg') $ext = 'jpeg';
  273. if($ext=='png') imagesavealpha($this->image, true);
  274. if($file == null)
  275. $file = $this->file;
  276. $fn = 'image'.$ext;
  277. if($ext == 'jpeg')
  278. $fn($this->image, $file,100);
  279. else
  280. $fn($this->image, $file);
  281. // If there is a new filename change the internal name too
  282. if($file) $this->file = $file;
  283. return true;
  284. } else
  285. return false;
  286. }
  287. /**
  288. * Saves the image to the given path
  289. *
  290. * @param string $file Leave empty to replace the original file
  291. * @return Image
  292. */
  293. public function save($file = null){
  294. if(empty($this->image)) return $this;
  295. if(!$file) $file = $this->file;
  296. $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
  297. if(!$ext){
  298. $file .= '.'.$this->meta['ext'];
  299. $ext = $this->meta['ext'];
  300. }
  301. if($ext=='jpg') $ext = 'jpeg';
  302. if(!in_array($ext, array('png', 'jpeg', 'gif')))
  303. return $this;
  304. $this->process($ext, $file);
  305. return $this;
  306. }
  307. /**
  308. * Outputs the manipulated image
  309. *
  310. * @return Image
  311. */
  312. public function show(){
  313. if(empty($this->image)) return $this;
  314. header('Content-type: '.$this->meta['mime']);
  315. $this->process();
  316. return $this;
  317. }
  318. }