PageRenderTime 25ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Images.class.php

https://gitlab.com/karl3/gs_libs
PHP | 376 lines | 195 code | 44 blank | 137 comment | 31 complexity | fbbb259d555fcca92fda705f1436d8d0 MD5 | raw file
  1. <?php
  2. /**
  3. *
  4. * Class for handling images using GD, primarily via file upload
  5. *
  6. * SOME USAGE EXAMPLES FOR THE uploadFile METHOD, WHICH IS THE PRIMARY REASON THIS CLASS EXISTS
  7. *
  8. * // Do Not retain original, create a safe "full" image, a thumbnail, and a smaller thumbnail
  9. * $file_info = Images::uploadFile('item_pic', $_SERVER['DOCUMENT_ROOT'] . '/images/bodyparts/',
  10. * FALSE, $config['max_bp_img'], $config['max_bp_img_lgthumb'], $config['max_bp_img_smthumb']);
  11. *
  12. * // Retain original, create a safe "full" image, a thumbnail, and a smaller thumbnail
  13. * $file_info = Images::uploadFile('item_pic', $_SERVER['DOCUMENT_ROOT'] . '/images/bodyparts/',
  14. * TRUE, $config['max_bp_img'], $config['max_bp_img_lgthumb'], $config['max_bp_img_smthumb']);
  15. *
  16. * // retain the original, no safe "full" image, no thumbnails
  17. * $file_info = Images::uploadFile('item_pic', $_SERVER['DOCUMENT_ROOT'] . '/images/bodyparts/',
  18. * TRUE, NULL, NULL, NULL);
  19. *
  20. * // do not retain the original, create only the safe "full" image
  21. * $file_info = Images::uploadFile('item_pic', $_SERVER['DOCUMENT_ROOT'] . '/images/bodyparts/',
  22. * FALSE, $config['max_bp_img'], NULL, NULL);
  23. *
  24. * // retain the original, no safe "full" image, create a thumbnail and a smaller thumbnail
  25. * $file_info = Images::uploadFile('item_pic', $_SERVER['DOCUMENT_ROOT'] . '/images/bodyparts/',
  26. * TRUE, NULL, $config['max_bp_img_lgthumb'], $config['max_bp_img_smthumb']);
  27. *
  28. *
  29. * @todo figure out how to resize animated gifs, keeping the animation
  30. * @author Karl Groves <karl@karlgroves.com>
  31. */
  32. class Images
  33. {
  34. /**
  35. *
  36. * @return array
  37. */
  38. public static function getValMsgArray()
  39. {
  40. return array(1 => _('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
  41. 2 => _('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
  42. 3 => _('The uploaded file was only partially uploaded'),
  43. 4 => _('No file was uploaded'),
  44. 6 => _('Missing a temporary folder'),
  45. 7 => _('Failed to write file to disk.'),
  46. 8 => _('A PHP extension stopped the file upload.'));
  47. }
  48. /**
  49. *
  50. * @param string $src_image
  51. * @param string $dest_image
  52. * @param int $thumb_size
  53. * @param int $jpg_quality
  54. *
  55. * @return bool
  56. */
  57. public static function square_crop($src_image, $dest_image, $thumb_size = 50, $jpg_quality = 90)
  58. {
  59. // Get dimensions of existing image
  60. $image = getimagesize($src_image);
  61. // Check for valid dimensions
  62. if ($image[0] <= 0 || $image[1] <= 0) {
  63. //echo "ERROR";
  64. return false;
  65. }
  66. // Determine format from MIME-Type
  67. $image['format'] = strtolower(preg_replace('/^.*?\//', '', $image['mime']));
  68. // Import image
  69. switch ($image['format']) {
  70. case 'jpg' :
  71. case 'jpeg' :
  72. $image_data = imagecreatefromjpeg($src_image);
  73. break;
  74. case 'png' :
  75. $image_data = imagecreatefrompng($src_image);
  76. break;
  77. case 'gif' :
  78. $image_data = imagecreatefromgif($src_image);
  79. break;
  80. default :
  81. // Unsupported format
  82. return false;
  83. break;
  84. }
  85. // end switch
  86. // Verify import
  87. if ($image_data == false) {
  88. echo "ERROR";
  89. return false;
  90. }
  91. // Calculate measurements
  92. if ($image[0] > $image[1]) {
  93. // For landscape images
  94. $x_offset = ($image[0] - $image[1]) / 2;
  95. $y_offset = 0;
  96. $square_size = $image[0] - ($x_offset * 2);
  97. } else {
  98. // For portrait and square images
  99. $x_offset = 0;
  100. $y_offset = ($image[1] - $image[0]) / 2;
  101. $square_size = $image[1] - ($y_offset * 2);
  102. }
  103. // Resize and crop
  104. $canvas = imagecreatetruecolor($thumb_size, $thumb_size);
  105. if (imagecopyresampled($canvas, $image_data, 0, 0, $x_offset, $y_offset, $thumb_size, $thumb_size, $square_size, $square_size)) {
  106. // Create thumbnail
  107. switch (strtolower(preg_replace('/^.*\./', '', $dest_image))) {
  108. case 'jpg' :
  109. case 'jpeg' :
  110. return imagejpeg($canvas, $dest_image, $jpg_quality);
  111. break;
  112. case 'png' :
  113. return imagepng($canvas, $dest_image);
  114. break;
  115. case 'gif' :
  116. return imagegif($canvas, $dest_image);
  117. break;
  118. default :
  119. // Unsupported format
  120. return false;
  121. break;
  122. }
  123. } else {
  124. return false;
  125. }
  126. }
  127. /**
  128. * Create a thumbnail image from $inputFileName no taller or wider than
  129. * $maxSize. Returns the new image resource or false on error.
  130. * Author: mthorn.net
  131. *
  132. * @param string $inputFileName
  133. * @param int $maxSize
  134. *
  135. * @return string
  136. */
  137. public static function thumbnail($inputFileName, $maxSize = 100)
  138. {
  139. $info = getimagesize($inputFileName);
  140. $type = isset($info['type']) ? $info['type'] : $info[2];
  141. // Check support of file type
  142. if (!(imagetypes() & $type)) {
  143. // Server does not support file type
  144. return false;
  145. }
  146. $width = isset($info['width']) ? $info['width'] : $info[0];
  147. $height = isset($info['height']) ? $info['height'] : $info[1];
  148. // Calculate aspect ratio
  149. $wRatio = $maxSize / $width;
  150. $hRatio = $maxSize / $height;
  151. // Using imagecreatefromstring will automatically detect the file type
  152. $sourceImage = imagecreatefromstring(file_get_contents($inputFileName));
  153. // Calculate a proportional width and height no larger than the max size.
  154. if (($width <= $maxSize) && ($height <= $maxSize)) {
  155. // Input is smaller than thumbnail, do nothing
  156. return $sourceImage;
  157. } elseif (($wRatio * $height) < $maxSize) {
  158. // Image is horizontal
  159. $tHeight = ceil($wRatio * $height);
  160. $tWidth = $maxSize;
  161. } else {
  162. // Image is vertical
  163. $tWidth = ceil($hRatio * $width);
  164. $tHeight = $maxSize;
  165. }
  166. $thumb = imagecreatetruecolor($tWidth, $tHeight);
  167. if ($sourceImage === false) {
  168. // Could not load image
  169. return false;
  170. }
  171. // Copy resampled makes a smooth thumbnail
  172. imagecopyresampled($thumb, $sourceImage, 0, 0, 0, 0, $tWidth, $tHeight, $width, $height);
  173. imagedestroy($sourceImage);
  174. return $thumb;
  175. }
  176. /**
  177. * Save the image to a file. Type is determined from the extension.
  178. * $quality is only used for jpegs.
  179. * Author: mthorn.net
  180. *
  181. * @param resource $im resource handler for the new image
  182. * @param string $fileName name for the new image
  183. * @param int $quality quality of the image, only relevant if jpg/ jpeg
  184. *
  185. * @return bool
  186. */
  187. public static function imageToFile($im, $fileName, $quality = 90)
  188. {
  189. if (!$im || file_exists($fileName)) {
  190. return false;
  191. }
  192. $ext = strtolower(substr($fileName, strrpos($fileName, '.')));
  193. switch ($ext) {
  194. case '.gif' :
  195. imagegif($im, $fileName);
  196. break;
  197. case '.jpg' :
  198. case '.jpeg' :
  199. imagejpeg($im, $fileName, $quality);
  200. break;
  201. case '.png' :
  202. imagepng($im, $fileName);
  203. break;
  204. case '.bmp' :
  205. imagewbmp($im, $fileName);
  206. break;
  207. default :
  208. return false;
  209. }
  210. return true;
  211. }
  212. /**
  213. *
  214. * Thanks to ZeBadger for original example, and Davide Gualano for pointing me to it
  215. * Original at http://it.php.net/manual/en/function.imagecreatefromgif.php#59787
  216. *
  217. * @param string $filename
  218. *
  219. * @return bool
  220. */
  221. public static function is_animated_gif($filename)
  222. {
  223. $raw = file_get_contents($filename);
  224. $offset = 0;
  225. $frames = 0;
  226. while ($frames < 2) {
  227. $where1 = strpos($raw, "\x00\x21\xF9\x04", $offset);
  228. if ($where1 === false) {
  229. break;
  230. } else {
  231. $offset = $where1 + 1;
  232. $where2 = strpos($raw, "\x00\x2C", $offset);
  233. if ($where2 === false) {
  234. break;
  235. } else {
  236. if ($where1 + 8 == $where2) {
  237. $frames++;
  238. }
  239. $offset = $where2 + 1;
  240. }
  241. }
  242. }
  243. return $frames > 1;
  244. }
  245. /**
  246. *
  247. * removes anything non alphanumeric from the file name
  248. *
  249. * @param string $image_name
  250. *
  251. * @return string
  252. */
  253. public static function cleanFileName($image_name)
  254. {
  255. $image_name = preg_replace("/[^a-zA-Z0-9]/", "", $image_name);
  256. $remove_these = array(' ', '`', '"', '\'', '\\', '/', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=', '{', '}', '[', ']', '|', ':', ';', '<', ',', '>', '?');
  257. $image_name = str_replace($remove_these, '', $image_name);
  258. return $image_name;
  259. }
  260. /**
  261. *
  262. * @param string $varName
  263. * @param string $tmpPath
  264. * @param bool $retainOrig
  265. * @param int $maxSize
  266. * @param int $lgThumbSize
  267. * @param int $sqThumbSize
  268. *
  269. * @return string
  270. */
  271. public static function uploadFile($varName, $tmpPath, $retainOrig = true, $maxSize = null, $lgThumbSize = null, $sqThumbSize = null)
  272. {
  273. // if the file size isn't greater than zero, return false
  274. if (!$_FILES[$varName]['size'] > 0) {
  275. return false;
  276. }
  277. foreach ($_FILES[$varName] AS $key => $val) {
  278. $output[$key] = $val;
  279. }
  280. //echo "<hr>FROM IMAGES.CLASS.PHP";
  281. //echo "image_name: " . $_FILES[$varName]['name'] . "<br>\n";
  282. //echo "file_type: " . $_FILES[$varName]['type'] . "<br>\n";
  283. //echo "file_size: " . $_FILES[$varName]['size'] . "<br>\n";
  284. //echo "temp_name: " . $_FILES[$varName]['tmp_name'] . "<br>\n";
  285. //echo "error_code: " . $_FILES[$varName]['error'] . "<br>\n";
  286. $image_name = Images::cleanFileName($_FILES[$varName]['name']);
  287. $output['destination'] = $tmpPath . $image_name;
  288. //echo "Destination: " . $output['destination'] . " <br>\n";
  289. // if the file already exists in the site, rename it
  290. $num = 1;
  291. while (file_exists($output['destination'])) {
  292. $num++;
  293. // if previous file name existed then try another number+_+filename
  294. $image_name = $num . "" . $image_name;
  295. $output['destination'] = $tmpPath . $image_name;
  296. }
  297. //echo "Final Destination: " . $output['destination'] . " <br>\n";
  298. $output['name'] = $image_name;
  299. // copy the image to the destination
  300. move_uploaded_file($_FILES['item_pic']['tmp_name'], $output['destination']) or die("Picture upload failed");
  301. // this creates the thumbnail
  302. $infile = $tmpPath . $image_name;
  303. //echo "Infile $infile <br>\n";
  304. // get the DATA size of the file
  305. $imgsize = filesize($infile);
  306. //echo "Image Data Size: $imgsize <br>\n";
  307. // resize it to the maximum allowed size
  308. if (!is_null($maxSize)) {
  309. $full = Images::thumbnail($infile, $maxSize);
  310. $output['final_img'] = $maxSize . "_" . $image_name;
  311. Images::imageToFile($full, $tmpPath . $output['final_img']);
  312. }
  313. // if we're creating a large thumbnail, let's do it
  314. if (!is_null($lgThumbSize)) {
  315. $im = Images::thumbnail($infile, $lgThumbSize);
  316. $output['final_lg_thumb'] = $lgThumbSize . "_" . $image_name;
  317. Images::imageToFile($im, $tmpPath . $output['final_lg_thumb']);
  318. }
  319. // if we're creating a small thumbnail, let's do it
  320. if (!is_null($sqThumbSize)) {
  321. // Make the Square Thumbnail
  322. $output['final_sq_thumb'] = $sqThumbSize . "_" . $image_name;
  323. Images::square_crop($infile, $tmpPath . $output['final_sq_thumb'], $sqThumbSize);
  324. }
  325. // if we're not retaining the original, then dump it
  326. if (false === $retainOrig) {
  327. unlink($output['destination']);
  328. $output['destination'] = '';
  329. }
  330. return $output;
  331. }
  332. }