PageRenderTime 26ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/img.php

https://github.com/davidturner/Wee_
PHP | 265 lines | 181 code | 37 blank | 47 comment | 32 complexity | 72a98eb057ebf6e8a4eaef0b004fa911 MD5 | raw file
  1. <?php
  2. /* PROJECT INFO --------------------------------------------------------------------------------------------------------
  3. Version: 1.3.6
  4. Changelog: http://adaptive-images.com/changelog.txt
  5. Homepage: http://adaptive-images.com
  6. GitHub: https://github.com/MattWilcox/Adaptive-Images
  7. Twitter: @responsiveimg
  8. LEGAL:
  9. Adaptive Images by Matt Wilcox is licensed under a Creative Commons Attribution 3.0 Unported License.
  10. /* CONFIG ----------------------------------------------------------------------------------------------------------- */
  11. $resolutions = array(1382, 992, 768, 480); // the resolution break-points to use (screen widths, in pixels)
  12. $cache_path = "cache-img"; // where to store the generated re-sized images. This folder must be writable.
  13. $jpg_quality = 80; // the quality of any generated JPGs on a scale of 0 to 100
  14. $sharpen = TRUE; // Shrinking images can blur details, perform a sharpen on re-scaled images?
  15. $watch_cache = TRUE; // check that the responsive image isn't stale (ensures updated source images are re-cached)
  16. $browser_cache = 60*60*24*7; // How long the BROWSER cache should last (seconds, minutes, hours, days. 7days by default)
  17. $mobile_first = TRUE; // If there's no cookie FALSE sends the largest $resolutions version (TRUE sends smallest)
  18. /* END CONFIG ----------------------------------------------------------------------------------------------------------
  19. ------------------------ Don't edit anything after this line unless you know what you're doing -------------------------
  20. --------------------------------------------------------------------------------------------------------------------- */
  21. /* get all of the required data from the HTTP request */
  22. $document_root = $_SERVER['DOCUMENT_ROOT'];
  23. $requested_uri = parse_url(urldecode($_SERVER['REQUEST_URI']), PHP_URL_PATH);
  24. $requested_file = basename($requested_uri);
  25. if(file_exists($document_root.'/categories'.$requested_uri)){
  26. $source_file = $document_root.'/categories'.$requested_uri;
  27. } elseif (file_exists($document_root.'/categories/pages'.$requested_uri)) {
  28. $source_file = $document_root.'/categories/pages'.$requested_uri;
  29. } elseif(file_exists($document_root.'/assets/default/'.$requested_uri)) {
  30. $source_file = $document_root.'/assets/default/'.$requested_uri;
  31. } else {
  32. $source_file = $document_root.$requested_uri;
  33. }
  34. $resolution = FALSE;
  35. /* Browser engine detect
  36. NOTE: only required to work around a bug where some browsers can't set the cookie fast enough on the first visit to the
  37. website. Such browsers therefor act as though no cookie was set on the very first visit. This means we can't
  38. allow desktop browsers to have $mobile_first = TRUE (which we don't want anyway) */
  39. function browser_detect() {
  40. $userAgent = strtolower($_SERVER['HTTP_USER_AGENT']);
  41. // Identify the OS platform. Match only desktop OSs
  42. if (
  43. strpos($userAgent,'macintosh') ||
  44. strpos($userAgent,'windows nt') ||
  45. strpos($userAgent,'x11')
  46. ) {
  47. return TRUE;
  48. }
  49. }
  50. /* Do we need to switch mobile first off? */
  51. if(browser_detect()){
  52. $mobile_first = FALSE;
  53. }
  54. /* helper function: Send headers and returns an image. */
  55. function sendImage($filename, $browser_cache) {
  56. $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
  57. if (in_array($extension, array('png', 'gif', 'jpeg'))) {
  58. header("Content-Type: image/".$extension);
  59. } else {
  60. header("Content-Type: image/jpeg");
  61. }
  62. header("Cache-Control: private, max-age=".$browser_cache);
  63. header('Expires: '.gmdate('D, d M Y H:i:s', time()+$browser_cache).' GMT');
  64. header('Content-Length: '.filesize($filename));
  65. readfile($filename);
  66. exit();
  67. }
  68. /* helper function: Create and send an image with an error message. */
  69. function sendErrorImage($message) {
  70. $im = ImageCreateTrueColor(800, 200);
  71. $text_color = ImageColorAllocate($im, 233, 14, 91);
  72. ImageString($im, 1, 5, 5, $message, $text_color);
  73. header("Cache-Control: no-store");
  74. header('Expires: '.gmdate('D, d M Y H:i:s', time()-1000).' GMT');
  75. header('Content-Type: image/jpeg');
  76. ImageJpeg($im);
  77. ImageDestroy($im);
  78. exit();
  79. }
  80. /* sharpen images function */
  81. function findSharp($intOrig, $intFinal) {
  82. $intFinal = $intFinal * (750.0 / $intOrig);
  83. $intA = 52;
  84. $intB = -0.27810650887573124;
  85. $intC = .00047337278106508946;
  86. $intRes = $intA + $intB * $intFinal + $intC * $intFinal * $intFinal;
  87. return max(round($intRes), 0);
  88. }
  89. /* refreshes the cached image if it's outdated */
  90. function refreshCache($source_file, $cache_file, $resolution) {
  91. if (file_exists($cache_file)) {
  92. // not modified
  93. if (filemtime($cache_file) >= filemtime($source_file)) {
  94. return $cache_file;
  95. }
  96. // modified, clear it
  97. unlink($cache_file);
  98. }
  99. return generateImage($source_file, $cache_file, $resolution);
  100. }
  101. /* generates the given cache file for the given source file with the given resolution */
  102. function generateImage($source_file, $cache_file, $resolution) {
  103. global $sharpen, $jpg_quality;
  104. $extension = strtolower(pathinfo($source_file, PATHINFO_EXTENSION));
  105. // Check the image dimensions
  106. $dimensions = GetImageSize($source_file);
  107. $width = $dimensions[0];
  108. $height = $dimensions[1];
  109. // Do we need to downscale the image?
  110. if ($width <= $resolution) { // no, because the width of the source image is already less than the client width
  111. return $source_file;
  112. }
  113. // We need to resize the source image to the width of the resolution breakpoint we're working with
  114. $ratio = $height/$width;
  115. $new_width = $resolution;
  116. $new_height = ceil($new_width * $ratio);
  117. switch ($extension) {
  118. case 'png':
  119. $src = @ImageCreateFromPng($source_file); // original image
  120. break;
  121. case 'gif':
  122. $src = @ImageCreateFromGif($source_file); // original image
  123. break;
  124. default:
  125. $src = @ImageCreateFromJpeg($source_file); // original image
  126. break;
  127. }
  128. $dst = ImageCreateTrueColor($new_width, $new_height); // re-sized image
  129. if($extension=='png'){
  130. imagealphablending($dst, false);
  131. imagesavealpha($dst,true);
  132. $transparent = imagecolorallocatealpha($dst, 255, 255, 255, 127);
  133. imagefilledrectangle($dst, 0, 0, $new_width, $new_height, $transparent);
  134. }
  135. ImageCopyResampled($dst, $src, 0, 0, 0, 0, $new_width, $new_height, $width, $height); // do the resize in memory
  136. ImageDestroy($src);
  137. // sharpen the image?
  138. // NOTE: requires PHP compiled with the bundled version of GD (see http://php.net/manual/en/function.imageconvolution.php)
  139. if($sharpen == TRUE && function_exists('imageconvolution')) {
  140. $intSharpness = findSharp($width, $new_width);
  141. $arrMatrix = array(
  142. array(-1, -2, -1),
  143. array(-2, $intSharpness + 12, -2),
  144. array(-1, -2, -1)
  145. );
  146. imageconvolution($dst, $arrMatrix, $intSharpness, 0);
  147. }
  148. $cache_dir = dirname($cache_file);
  149. // does the directory exist already?
  150. if (!is_dir($cache_dir)) {
  151. if (!mkdir($cache_dir, 0777, true)) {
  152. // check again if it really doesn't exist to protect against race conditions
  153. if (!is_dir($cache_dir)) {
  154. // uh-oh, failed to make that directory
  155. ImageDestroy($dst);
  156. sendErrorImage("Failed to create directory: $cache_dir");
  157. }
  158. }
  159. }
  160. if (!is_writable($cache_dir)) {
  161. sendErrorImage("The cache directory is not writable: $cache_dir");
  162. }
  163. // save the new file in the appropriate path, and send a version to the browser
  164. switch ($extension) {
  165. case 'png':
  166. $gotSaved = ImagePng($dst, $cache_file);
  167. break;
  168. case 'gif':
  169. $gotSaved = ImageGif($dst, $cache_file);
  170. break;
  171. default:
  172. $gotSaved = ImageJpeg($dst, $cache_file, $jpg_quality);
  173. break;
  174. }
  175. ImageDestroy($dst);
  176. if (!$gotSaved && !file_exists($cache_file)) {
  177. sendErrorImage("Failed to create image: $cache_file");
  178. }
  179. return $cache_file;
  180. }
  181. // check if the file exists at all
  182. if (!file_exists($source_file)) {
  183. header("Status: 404 Not Found");
  184. exit();
  185. }
  186. /* check that PHP has the GD library available to use for image re-sizing */
  187. if (!extension_loaded('gd')) { // it's not loaded
  188. if (!function_exists('dl') || !dl('gd.so')) { // and we can't load it either
  189. // no GD available, so deliver the image straight up
  190. trigger_error('You must enable the GD extension to make use of Adaptive Images', E_USER_WARNING);
  191. sendImage($source_file, $browser_cache);
  192. }
  193. }
  194. /* Check to see if a valid cookie exists */
  195. if (isset($_COOKIE['resolution'])) {
  196. if (is_numeric($_COOKIE['resolution'])) {
  197. $client_width = (int) $_COOKIE["resolution"]; // store the cookie value in a variable
  198. /* the client width in the cookie is valid, now fit that number into the correct resolution break point */
  199. rsort($resolutions); // make sure the supplied break-points are in reverse size order
  200. $resolution = $resolutions[0]; // by default it's the largest supported break-point
  201. foreach ($resolutions as $break_point) { // filter down
  202. if ($client_width <= $break_point) {
  203. $resolution = $break_point;
  204. }
  205. }
  206. } else {
  207. setcookie("resolution", "", time() -1); // delete the mangled cookie
  208. }
  209. }
  210. /* No resolution was found (no cookie or invalid cookie) */
  211. if (!$resolution) {
  212. // We send the lowest resolution for mobile-first approach, and highest otherwise
  213. $resolution = $mobile_first ? min($resolutions) : max($resolutions);
  214. }
  215. $cache_file = $document_root."/$cache_path/$resolution/".$requested_uri;
  216. /* Use the resolution value as a path variable and check to see if an image of the same name exists at that path */
  217. if (file_exists($cache_file)) { // it exists cached at that size
  218. if ($watch_cache) { // if cache watching is enabled, compare cache and source modified dates to ensure the cache isn't stale
  219. $cache_file = refreshCache($source_file, $cache_file, $resolution);
  220. }
  221. sendImage($cache_file, $browser_cache);
  222. }
  223. /* It exists as a source file, so lets work with that: */
  224. $file = generateImage($source_file, $cache_file, $resolution);
  225. sendImage($file, $browser_cache);