imagecache_autorotate.module 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <?php
  2. /**
  3. * @file
  4. * Autorotate image based on EXIF Orientation tag.
  5. * http://sylvana.net/jpegcrop/exif_orientation.html
  6. *
  7. * This mini-module contributed by jonathan_hunt http://drupal.org/user/28976
  8. * September 1, 2009
  9. *
  10. * Tweaked by dman to add documentation
  11. */
  12. /* In Adobe PNGs and TIFF, this information MAY be present in the XMP
  13. * metadata like so:
  14. <x:xmpmeta xmlns:x="adobe:ns:meta/">
  15. <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  16. <rdf:Description rdf:about="" xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
  17. <tiff:Orientation>6</tiff:Orientation>
  18. </rdf:Description>
  19. </rdf:RDF>
  20. </x:xmpmeta>
  21. */
  22. function imagecache_autorotate_image_effect_info() {
  23. $effects = array();
  24. $effects['imagecache_autorotate'] = array(
  25. 'label' => t('Autorotate'),
  26. 'help' => t('Add autorotate image based on EXIF Orientation.'),
  27. 'effect callback' => 'imagecache_autorotate_image',
  28. 'dimensions callback' => 'imagecache_autorotate_dimensions',
  29. );
  30. return $effects;
  31. }
  32. /**
  33. * @todo: This form is no longer needed nor defined in the hook above. If this
  34. * information still needs to be displayed it should probably be moved to help.
  35. */
  36. function imagecache_autorotate_form() {
  37. $form = array();
  38. $form['help'] = array(
  39. '#type' => 'markup',
  40. '#value' => "<p>
  41. <b>There are no user-configurable options for this process.</b>
  42. </p><p>
  43. Certain cameras can embed <em>orientation</em> information into image
  44. files when they save them. This information is embedded in an EXIF tag
  45. and can be used to rotate images to their correct position for display.
  46. </p><p>
  47. <em>Not all cameras or images contain this information.</em>
  48. This process is only useful for those that do.
  49. </p><p>
  50. The expected/supported values are
  51. <br/><strong>Tag</strong>: <code>0x0112 Orientation</code>
  52. </p>
  53. <ul>
  54. <li>1 = Horizontal (normal)</li>
  55. <li>3 = Rotate 180</li>
  56. <li>6 = Rotate 90 CW</li>
  57. <li>8 = Rotate 270 CW</li>
  58. </ul>
  59. <p>
  60. <a href='http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html'>
  61. EXIF Reference</a>
  62. </p>
  63. ",
  64. );
  65. return $form;
  66. }
  67. /**
  68. * Autorotate image based on EXIF Orientation tag.
  69. *
  70. * See code at
  71. * http://sylvana.net/jpegcrop/exif_orientation.html
  72. *
  73. * and reference at
  74. * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
  75. *
  76. * @todo:
  77. * Add horizontal and vertical flips etc.
  78. * Need to create sample set for tests.
  79. */
  80. function imagecache_autorotate_image($image, $data) {
  81. // Test to see if EXIF is supported for image type (e.g. not PNG).
  82. if ($image->info['mime_type'] == 'image/jpeg') {
  83. if (!function_exists('exif_read_data')) {
  84. watchdog('image', 'The image %file could not be auto-rotated because the exif_read_data() function is not available in this PHP installation. You probably will have to enable the exif extension.', array('%file' => $image->source));
  85. return FALSE;
  86. }
  87. $exif = exif_read_data(drupal_realpath($image->source));
  88. if (isset($exif['Orientation'])) {
  89. switch ($exif['Orientation']) {
  90. case 3:
  91. $degrees = 180;
  92. break;
  93. case 6:
  94. $degrees = 90;
  95. break;
  96. case 8:
  97. $degrees = 270;
  98. break;
  99. default:
  100. $degrees = 0;
  101. }
  102. if ($degrees != 0) {
  103. $org_width = $image->info['width'];
  104. $org_height = $image->info['height'];
  105. image_rotate($image, $degrees);
  106. if (($degrees === 90 || $degrees === 270) && $image->info['width'] === $org_width) {
  107. // The toolkit failed to alter the dimensions (imagemagick currently
  108. // fails to do so). So we do it ourselves.
  109. $image->info['width'] = $org_height;
  110. $image->info['height'] = $org_width;
  111. }
  112. }
  113. }
  114. }
  115. else if ($image->source === 'modules/image/sample.png' && !function_exists('exif_read_data')) {
  116. // Issue a warning if we are in the admin screen and the exif extension is
  117. // not enabled.
  118. drupal_set_message(t('The exif_read_data() function is not available in this PHP installation. You probably will have to enable the exif extension.'), 'warning');
  119. }
  120. return TRUE;
  121. }
  122. /**
  123. * Image dimensions callback; Auto-rotate.
  124. *
  125. * @param array $dimensions
  126. * An array with the dimensions (in pixels) to be modified.
  127. * @param array $data
  128. * An array of parameters for the autorotate effect (empty for this effect).
  129. */
  130. function imagecache_autorotate_dimensions(array &$dimensions, array $data) {
  131. // We can only know the resulting dimensions if both dimensions are equal.
  132. // Otherwise we need to inspect the image itself, which is not passed in here.
  133. // (this callback was introduced to enhance performance by not accessing the
  134. // image file when rendering the width and height attributes of the html img
  135. // tag).
  136. if ($dimensions['width'] !== $dimensions['height']) {
  137. $dimensions['width'] = $dimensions['height'] = NULL;
  138. }
  139. }