diff --git a/carl_util/basic/image_funcs.php b/carl_util/basic/image_funcs.php index f22f04b25..633a0d805 100644 --- a/carl_util/basic/image_funcs.php +++ b/carl_util/basic/image_funcs.php @@ -54,6 +54,39 @@ function resize_image($path, $width, $height, $sharpen=true) return $result; } +/** + * Auto orient an image based on EXIF orientation flag, and set the flag to 1 (defualt). + * + * The image will be rotated in place; to avoid this, make a {@link copy} of + * the original image first, and auto-orient the copy. + * + * Raises a {@link WARNING} if imagemagick is not available. + * + * @param string $path filesystem path to the image to be auto-oriented + * @return boolean true if the image was auto-oriented successfully; false if not + */ +function auto_orient_image($path) { + if (!is_file($path) || !is_readable($path)) { + trigger_error('cannot auto orient image; no file exists at the given path '. + '('.var_export($path, true).')', WARNING); + return false; + } + + $perms = substr(sprintf('%o', fileperms($path)), -4); + if (imagemagick_available()) { + $result = _imagemagick_auto_orient($path); + } else { + trigger_error('ImageMagick is not available; cannot auto-orient image', WARNING); + return false; + } + + // Prevent the transformation from changing the file permissions. + clearstatcache(); + $newperms = substr(sprintf('%o', fileperms($path)), -4); + if ($perms != $newperms) @chmod($path, octdec($perms)); + return $result; +} + /** * Convert some file to an image - places the file in the same place. * Right now just png is supported - other formats could be. @@ -1079,6 +1112,36 @@ function _gd_resize($path, $width, $height, $sharpen) return $success; } +/** + * @access private + */ +function _imagemagick_auto_orient($path) { + if (defined('IMAGEMAGICK_PATH')) { + $exec = (substr(IMAGEMAGICK_PATH, -1) == DIRECTORY_SEPARATOR) + ? IMAGEMAGICK_PATH.'mogrify' + : IMAGEMAGICK_PATH.DIRECTORY_SEPARATOR."mogrify"; + } else { + $exec = "mogrify"; + } + + $args = array( + $exec, + '-auto-orient', + ); + $args[] = escapeshellarg($path); + + $output = array(); + $exit_status = -1; + exec(implode(' ', $args), $output, $exit_status); + if ($exit_status != 0) { + trigger_error('image auto orient failed: '.implode('; ', $output), WARNING); + error_log(implode(' ', $args)); + return false; + } + + return true; +} + /** * Gets the components of an RGB color. * @param int $color an RGB color @@ -1093,6 +1156,8 @@ function get_color_components($color) } + + /** * Sharpens a GD image using an unsharp mask. * The given image will be sharpened in-place; this function returns the same diff --git a/reason_4.0/lib/core/classes/image_import.php b/reason_4.0/lib/core/classes/image_import.php index be9969c7b..6bdce3ecf 100644 --- a/reason_4.0/lib/core/classes/image_import.php +++ b/reason_4.0/lib/core/classes/image_import.php @@ -361,6 +361,9 @@ function process() $date = ''; + // Do we need to reorient based on exif flag? + $needs_reorienting = false; + // get suffix $type = strtolower( substr($cur_name,strrpos($cur_name,'.')+1) ); $ok_types = array('jpg'); @@ -383,11 +386,23 @@ function process() break; } } + + // Check orientation + if (!empty($exif_data['Orientation'])) { + if (1 != $exif_data['Orientation']) { + $needs_reorienting = true; + } + } } } else { $date = $this->get_value( 'datetime' ); + + // Maybe we couldn't read exif data in PHP, but imagemagick can + if (in_array($type, $ok_types)) { + $needs_reorienting = true; + } } $keywords = $entry; @@ -438,7 +453,6 @@ function process() if($page_id) create_relationship($page_id, $id, relationship_id_of('minisite_page_to_image'), array('rel_sort_order'=>$sort_order_value) ); - // resize and move photos $new_name = PHOTOSTOCK.$id.'.'.$type; $orig_name = PHOTOSTOCK.$id.'_orig.'.$type; @@ -459,6 +473,11 @@ function process() copy( $cur_name, $new_name ); } + // Reorient if needed + if ($needs_reorienting) { + auto_orient_image($new_name); + } + // create a thumbnail if need be list($width, $height, $type, $attr) = getimagesize($new_name); diff --git a/reason_4.0/lib/core/content_managers/image.php3 b/reason_4.0/lib/core/content_managers/image.php3 index d0e76c2b2..a4e43abc8 100644 --- a/reason_4.0/lib/core/content_managers/image.php3 +++ b/reason_4.0/lib/core/content_managers/image.php3 @@ -93,6 +93,7 @@ 'acceptable_types' => $acceptable_types) ); $image = $this->get_element('image'); + $image->get_head_items($this->head_items); $this->add_element('default_thumbnail', 'checkbox', array('description' => 'Generate thumbnail from full-size image')); diff --git a/reason_4.0/lib/core/scripts/upload/receive.php b/reason_4.0/lib/core/scripts/upload/receive.php index 46ed52e7c..3c7f42b02 100644 --- a/reason_4.0/lib/core/scripts/upload/receive.php +++ b/reason_4.0/lib/core/scripts/upload/receive.php @@ -130,6 +130,32 @@ function _json_encode_object($object) responseWrapper(501, 'Unable to convert the uploaded file to a web-friendly image'); } } + + // Read EXIF data to see if we can/should reorient + $needs_reorienting = false; + if (2 == $file_type) { + if (function_exists('read_exif_data')) { + $exif_data = @read_exif_data($temp_path); + if ($exif_data && !empty($exif_data['Orientation'])) { + if (1 != $exif_data['Orientation']) { + $needs_reorienting = true; + } + } + } else { + // If we can't check read the exif data, assume we need to reorient. + $needs_reorienting = true; + } + } + + // Reorient if necessary + if ($needs_reorienting) { + if (auto_orient_image($temp_path)) { + list($width, $height) = getimagesize($temp_path); + clearstatcache(); + $filesize = filesize($temp_path); + } + } + if ($img_info) { // fix a permission idiosyncrasy so the permissions are consistent @@ -169,7 +195,6 @@ function _json_encode_object($object) } } } - } /*