wr2x_image.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. /* Version: 1.7.2 - now with even more pixels */
  3. define('DEBUG', false); // Write debugging information to a log file
  4. define('SEND_ETAG', true); // You will want to disable this if you load balance multiple servers
  5. define('SEND_EXPIRES', true);
  6. define('SEND_CACHE_CONTROL', true);
  7. define('USE_X_SENDFILE', false); // This will reduce memory usage, but isn't enabled on all systems. If you have issues enabling this setting, contact your host
  8. define('DOWNSIZE_NOT_FOUND', true); // If a regular image is requested and not found, send a retina file instead?
  9. define('CACHE_TIME', 24*60*60); // 1 day
  10. define('DISABLE_RI_HEADER', false);
  11. $document_root = $_SERVER['DOCUMENT_ROOT'];
  12. $requested_uri = parse_url(urldecode($_SERVER['REQUEST_URI']), PHP_URL_PATH);
  13. $requested_file = basename($requested_uri);
  14. $source_file = $document_root.$requested_uri;
  15. $source_dirname = pathinfo($source_file, PATHINFO_DIRNAME);
  16. $source_filename = pathinfo($source_file, PATHINFO_FILENAME);
  17. $source_ext = pathinfo($source_file, PATHINFO_EXTENSION);
  18. $at2x_file = $source_dirname.'/'.$source_filename.'@2x.'.$source_ext;
  19. $at3x_file = $source_dirname.'/'.$source_filename.'@3x.'.$source_ext;
  20. $at4x_file = $source_dirname.'/'.$source_filename.'@4x.'.$source_ext;
  21. $cache_directive = 'must-revalidate';
  22. $status = 'regular image';
  23. if (DEBUG) {
  24. $_debug_fh = fopen('retinaimages.log', 'a');
  25. fwrite($_debug_fh, "* * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\n");
  26. fwrite($_debug_fh, print_r($_COOKIE, true)."\n\n");
  27. fwrite($_debug_fh, "document_root: {$document_root}\n");
  28. fwrite($_debug_fh, "requested_uri: {$requested_uri}\n");
  29. fwrite($_debug_fh, "requested_file: {$requested_file}\n");
  30. fwrite($_debug_fh, "source_file: {$source_file}\n");
  31. fwrite($_debug_fh, "source_ext: {$source_ext}\n");
  32. fwrite($_debug_fh, "@2x_file: {$at2x_file}\n");
  33. fwrite($_debug_fh, "@3x_file: {$at3x_file}\n");
  34. fwrite($_debug_fh, "@4x_file: {$at4x_file}\n");
  35. }
  36. // Image was requested
  37. if (in_array($source_ext, array('png', 'gif', 'jpg', 'jpeg', 'bmp'))) {
  38. // Check if a cookie is set
  39. $cookie_value = false;
  40. if (isset($_COOKIE['devicePixelRatio'])) {
  41. $cookie_value = intval($_COOKIE['devicePixelRatio']);
  42. }
  43. else {
  44. // Force revalidation of cache on next request
  45. $cache_directive = 'no-cache';
  46. $status = 'no cookie';
  47. }
  48. if (DEBUG) {
  49. fwrite($_debug_fh, "devicePixelRatio: {$cookie_value}\n");
  50. fwrite($_debug_fh, "cache_directive: {$cache_directive}\n");
  51. }
  52. // No need to check for retina images if screen is low DPR
  53. if ($cookie_value !== false && $cookie_value > 1) {
  54. // Check over images and match the largest resolution available
  55. foreach (array($at4x_file => 3, $at3x_file => 2, $at2x_file => 1) as $retina_file => $min_dpr) {
  56. if ($cookie_value > $min_dpr && file_exists($retina_file)) {
  57. $source_file = $retina_file;
  58. $status = 'retina image';
  59. break;
  60. }
  61. }
  62. }
  63. // Check if we can shrink a larger version of the image
  64. if (!file_exists($source_file) && DOWNSIZE_NOT_FOUND){
  65. // Check over increasingly larger images and see if one is available
  66. foreach (array($at2x_file, $at3x_file, $at4x_file) as $retina_file) {
  67. if (file_exists($retina_file)) {
  68. $source_file = $retina_file;
  69. $status = 'downsized image';
  70. break;
  71. }
  72. }
  73. }
  74. // Check if the image to send exists
  75. if (!file_exists($source_file)) {
  76. if (DEBUG) { fwrite($_debug_fh, "Image not found. Sending 404\n"); }
  77. if (!DISABLE_RI_HEADER) {
  78. header('X-Retina-Images: not found');
  79. }
  80. header('HTTP/1.1 404 Not Found', true);
  81. exit();
  82. }
  83. // Attach a Retina Images header for debugging
  84. if (!DISABLE_RI_HEADER) {
  85. header('X-Retina-Images: '.$status);
  86. }
  87. // Send cache headers
  88. if (SEND_CACHE_CONTROL) {
  89. header("Cache-Control: private, {$cache_directive}, max-age=".CACHE_TIME, true);
  90. }
  91. if (SEND_EXPIRES) {
  92. date_default_timezone_set('GMT');
  93. header('Expires: '.gmdate('D, d M Y H:i:s', time()+CACHE_TIME).' GMT', true);
  94. }
  95. if (SEND_ETAG) {
  96. $etag = '"'.filemtime($source_file).fileinode($source_file).'"';
  97. header("ETag: $etag", true);
  98. if (DEBUG) {
  99. fwrite($_debug_fh, "generated etag: {$etag}\n");
  100. if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
  101. fwrite($_debug_fh, "received etag: {$_SERVER['HTTP_IF_NONE_MATCH']}\n\n");
  102. }
  103. }
  104. if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && ($_SERVER['HTTP_IF_NONE_MATCH']) === $etag) {
  105. // File in cache hasn't change
  106. header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($source_file)).' GMT', true, 304);
  107. exit();
  108. }
  109. }
  110. if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === filemtime($source_file))) {
  111. // File in cache hasn't change
  112. header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($source_file)).' GMT', true, 304);
  113. exit();
  114. }
  115. // Send image headers
  116. if (in_array($source_ext, array('png', 'gif', 'jpeg', 'bmp'))) {
  117. header("Content-Type: image/".$source_ext, true);
  118. }
  119. else {
  120. header("Content-Type: image/jpeg", true);
  121. }
  122. header('Content-Length: '.filesize($source_file), true);
  123. // Close debug session if open
  124. if (DEBUG) {
  125. fwrite($_debug_fh, "sending file: {$source_file}\n\n");
  126. fclose($_debug_fh);
  127. }
  128. // Send file
  129. if (USE_X_SENDFILE) {
  130. header('X-Sendfile: '.$source_file);
  131. }
  132. else {
  133. readfile($source_file);
  134. }
  135. exit();
  136. }
  137. // DPR value was sent
  138. elseif(isset($_GET['devicePixelRatio'])) {
  139. $dpr = $_GET['devicePixelRatio'];
  140. // Validate value before setting cookie
  141. if (''.ceil(intval($dpr)) !== $dpr) {
  142. $dpr = '1';
  143. }
  144. setcookie('devicePixelRatio', $dpr);
  145. exit();
  146. }
  147. // Respond with an empty content
  148. header('HTTP/1.1 204 No Content', true);
  149. ?>