    diff --git src/wp-admin/includes/image-edit.php src/wp-admin/includes/image-edit.php
index db11b56..a998956 100644
--- src/wp-admin/includes/image-edit.php
+++ src/wp-admin/includes/image-edit.php
@@ -643,7 +643,7 @@ function wp_restore_image($post_id) {
 			if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
 
 				// Delete only if it's an edited image.
-				if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
+				if ( wp_get_image_edit_hash( $parts['basename'] ) ) {
 					wp_delete_file( $file );
 				}
 			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
@@ -666,7 +666,7 @@ function wp_restore_image($post_id) {
 				if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
 
 					// Delete only if it's an edited image.
-					if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) {
+					if ( wp_get_image_edit_hash( $meta['sizes'][$default_size]['file'] ) ) {
 						$delete_file = path_join( $parts['dirname'], $meta['sizes'][$default_size]['file'] );
 						wp_delete_file( $delete_file );
 					}
@@ -837,7 +837,7 @@ function wp_save_image( $post_id ) {
 	 */
 	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE && ! empty( $meta['sizes'] ) ) {
 		foreach ( $meta['sizes'] as $size ) {
-			if ( ! empty( $size['file'] ) && preg_match( '/-e[0-9]{13}-/', $size['file'] ) ) {
+			if ( ! empty( $size['file'] ) && wp_get_image_edit_hash( $size['file'] ) ) {
 				$delete_file = path_join( $dirname, $size['file'] );
 				wp_delete_file( $delete_file );
 			}
 
diff --git src/wp-includes/class-wp-image-editor-imagick.php src/wp-includes/class-wp-image-editor-imagick.php
index fc6fc93..69e51db 100644
--- src/wp-includes/class-wp-image-editor-imagick.php
+++ src/wp-includes/class-wp-image-editor-imagick.php
@@ -628,6 +628,11 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
 			$filename = $this->generate_filename( null, null, $extension );
 
 		try {
+			// Normalise exif orientation data to make it consistent across devices
+			if ( wp_get_image_edit_hash( $filename ) ) {
+				$this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT );
+			}
+
 			// Store initial Format
 			$orig_format = $this->image->getImageFormat();
 
diff --git src/wp-includes/media.php src/wp-includes/media.php
index ba52555..8ca68c4 100644
--- src/wp-includes/media.php
+++ src/wp-includes/media.php
@@ -1107,7 +1107,7 @@ function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac
 	 * contain a unique hash. Look for that hash and use it later to filter
 	 * out images that are leftovers from previous versions.
 	 */
-	$image_edited = preg_match( '/-e[0-9]{13}/', wp_basename( $image_src ), $image_edit_hash );
+	$image_edit_hash = wp_get_image_edit_hash( wp_basename( $image_src ) );
 
 	/**
 	 * Filters the maximum image width to be included in a 'srcset' attribute.
@@ -1147,7 +1147,7 @@ function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac
 		}
 
 		// Filter out images that are from previous edits.
-		if ( $image_edited && ! strpos( $image['file'], $image_edit_hash[0] ) ) {
+		if ( $image_edit_hash && ! strpos( $image['file'], $image_edit_hash ) ) {
 			continue;
 		}
 
@@ -1377,9 +1377,8 @@ function wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ) {
 	}
 
 	// Bail early if an image has been inserted and later edited.
-	if ( preg_match( '/-e[0-9]{13}/', $image_meta['file'], $img_edit_hash ) &&
-		strpos( wp_basename( $image_src ), $img_edit_hash[0] ) === false ) {
-
+	$img_edit_hash = wp_get_image_edit_hash( $image_meta['file'] );
+	if ( $img_edit_hash && strpos( wp_basename( $image_src ), $img_edit_hash ) === false ) {
 		return $image;
 	}
 
@@ -3850,3 +3849,16 @@ function wpview_media_sandbox_styles() {
 
 	return array( $mediaelement, $wpmediaelement );
 }
+
+/**
+ * Returns false or the edit hash if an image file has been edited in the media modal.
+ *
+ * @since 4.7.0
+ *
+ * @param string $filename
+ * @return string|false
+ */
+function wp_get_image_edit_hash( $filename ) {
+	$is_edited = preg_match( '/-(e[0-9]{13})[\.-]/', $filename, $image_edit_hash );
+	return $is_edited ? $image_edit_hash[1] : false;
+}

diff --git tests/phpunit/data/images/orientation-1.jpg tests/phpunit/data/images/orientation-1.jpg
new file mode 100644
index 0000000..015c5f1
Binary files /dev/null and tests/phpunit/data/images/orientation-1.jpg differ
diff --git tests/phpunit/data/images/orientation-2.jpg tests/phpunit/data/images/orientation-2.jpg
new file mode 100644
index 0000000..2e7fb57
Binary files /dev/null and tests/phpunit/data/images/orientation-2.jpg differ
diff --git tests/phpunit/data/images/orientation-3.jpg tests/phpunit/data/images/orientation-3.jpg
new file mode 100644
index 0000000..74505cf
Binary files /dev/null and tests/phpunit/data/images/orientation-3.jpg differ
diff --git tests/phpunit/data/images/orientation-4.jpg tests/phpunit/data/images/orientation-4.jpg
new file mode 100644
index 0000000..ea133fb
Binary files /dev/null and tests/phpunit/data/images/orientation-4.jpg differ
diff --git tests/phpunit/data/images/orientation-5.jpg tests/phpunit/data/images/orientation-5.jpg
new file mode 100644
index 0000000..81a8af6
Binary files /dev/null and tests/phpunit/data/images/orientation-5.jpg differ
diff --git tests/phpunit/data/images/orientation-6.jpg tests/phpunit/data/images/orientation-6.jpg
new file mode 100644
index 0000000..7426aba
Binary files /dev/null and tests/phpunit/data/images/orientation-6.jpg differ
diff --git tests/phpunit/data/images/orientation-7.jpg tests/phpunit/data/images/orientation-7.jpg
new file mode 100644
index 0000000..a541d95
Binary files /dev/null and tests/phpunit/data/images/orientation-7.jpg differ
diff --git tests/phpunit/data/images/orientation-8.jpg tests/phpunit/data/images/orientation-8.jpg
new file mode 100644
index 0000000..3f51d28
Binary files /dev/null and tests/phpunit/data/images/orientation-8.jpg differ
diff --git tests/phpunit/tests/image/orientation.php tests/phpunit/tests/image/orientation.php
new file mode 100644
index 0000000..a61a96d
--- /dev/null
+++ tests/phpunit/tests/image/orientation.php
@@ -0,0 +1,229 @@
+<?php
+require_once dirname( __FILE__ ) . '/base.php';
+
+/**
+ * Test the WP_Image_Editor base class
+ *
+ * @group image
+ * @group media
+ * @group orientation
+ */
+class Tests_Image_Editor_Orientation extends WP_Image_UnitTestCase {
+
+	public $editor_engine = 'WP_Image_Editor_Imagick';
+
+	public function setUp() {
+		require_once( ABSPATH . WPINC . '/class-wp-image-editor.php' );
+		require_once( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' );
+
+		parent::setUp();
+	}
+
+	/**
+	 * Test removing orientation exif data on rotate
+	 *
+	 * @ticket       37140
+	 *
+	 * @dataProvider get_images
+	 */
+	public function test_remove_orientation_data_on_rotate( $file ) {
+
+		preg_match( '/-(\d)\.(?:jpe?g|png|gif)$/', $file, $matches );
+		$orientation_value = intval( $matches[1] );
+
+		// Make sure we trigger wp_is_edited_image()
+		$file = $this->get_temp_edited_image( $file );
+
+		$data = wp_read_image_metadata( $file );
+
+		$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation value read from does not match image file exif data: ' . $file );
+
+		$temp_file = $this->get_temp_edited_image( $file, 'new' );
+
+		$image = wp_get_image_editor( $file );
+		$image->rotate( 180 );
+		$image->save( $temp_file );
+
+		$data = wp_read_image_metadata( $temp_file );
+
+		$this->assertEquals( 1, intval( $data['orientation'] ), 'Orientation exif data was not updated after rotating image: ' . $file );
+
+		unlink( $file );
+		unlink( $temp_file );
+	}
+
+	/**
+	 * Test removing orientation exif data on rotate
+	 *
+	 * @ticket       37140
+	 *
+	 * @dataProvider get_images
+	 */
+	public function test_remove_orientation_data_on_flip( $file ) {
+
+		preg_match( '/-(\d)\.(?:jpe?g|png|gif)$/', $file, $matches );
+		$orientation_value = intval( $matches[1] );
+
+		// Make sure we trigger wp_is_edited_image()
+		$file = $this->get_temp_edited_image( $file );
+
+		$data = wp_read_image_metadata( $file );
+
+		$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation value read from does not match image file exif data: ' . $file );
+
+		$temp_file = $this->get_temp_edited_image( $file, 'new' );
+
+		$image = wp_get_image_editor( $file );
+		$image->flip( true, true );
+		$image->save( $temp_file );
+
+		$data = wp_read_image_metadata( $temp_file );
+
+		$this->assertEquals( 1, intval( $data['orientation'] ), 'Orientation exif data was not updated after flipping image: ' . $file );
+
+		unlink( $file );
+		unlink( $temp_file );
+	}
+
+	/**
+	 * Test removing orientation exif data on resize
+	 *
+	 * @ticket       37140
+	 *
+	 * @dataProvider get_images
+	 */
+	public function test_remove_orientation_data_on_resize( $file ) {
+
+		preg_match( '/-(\d)\.(?:jpe?g|png|gif)$/', $file, $matches );
+		$orientation_value = intval( $matches[1] );
+
+		// Make sure we trigger wp_is_edited_image()
+		$file = $this->get_temp_edited_image( $file );
+
+		$data = wp_read_image_metadata( $file );
+
+		$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation value read from does not match image file exif data: ' . $file );
+
+		$temp_file = $this->get_temp_edited_image( $file, 'new' );
+
+		$image = wp_get_image_editor( $file );
+		$image->resize( 100, 100, true );
+		$image->save( $temp_file );
+
+		$data = wp_read_image_metadata( $temp_file );
+
+		$this->assertEquals( 1, intval( $data['orientation'] ), 'Orientation exif data was not updated after resizing image: ' . $file );
+
+		unlink( $file );
+		unlink( $temp_file );
+	}
+
+	/**
+	 * Test removing orientation exif data on crop
+	 *
+	 * @ticket       37140
+	 *
+	 * @dataProvider get_images
+	 */
+	public function test_remove_orientation_data_on_crop( $file ) {
+
+		preg_match( '/-(\d)\.(?:jpe?g|png|gif)$/', $file, $matches );
+		$orientation_value = intval( $matches[1] );
+
+		// Make sure we trigger wp_is_edited_image()
+		$file = $this->get_temp_edited_image( $file );
+
+		$data = wp_read_image_metadata( $file );
+
+		$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation value read from does not match image file exif data: ' . $file );
+
+		$temp_file = $this->get_temp_edited_image( $file, 'new' );
+
+		$image = wp_get_image_editor( $file );
+		$image->crop( 0, 0, 100, 100 );
+		$image->save( $temp_file );
+
+		$data = wp_read_image_metadata( $temp_file );
+
+		$this->assertEquals( 1, intval( $data['orientation'] ), 'Orientation exif data was not updated after cropping image: ' . $file );
+
+		unlink( $file );
+		unlink( $temp_file );
+	}
+
+	/**
+	 * Test preserve orientation exif data on resize non edited image
+	 *
+	 * @ticket       37140
+	 *
+	 * @dataProvider get_images
+	 */
+	public function test_preserve_orientation_data_on_resize( $file ) {
+
+		preg_match( '/-(\d)\.(?:jpe?g|png|gif)$/', $file, $matches );
+		$orientation_value = intval( $matches[1] );
+
+		$data = wp_read_image_metadata( $file );
+
+		$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation value read from does not match image file exif data: ' . $file );
+
+		$temp_file = wp_tempnam( $file ) . '.jpg';
+
+		$image = wp_get_image_editor( $file );
+		$image->resize( 100, 100, true );
+		$image->save( $temp_file );
+
+		$data = wp_read_image_metadata( $temp_file );
+
+		$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation exif data was not preserved after resizing unedited image: ' . $file );
+
+		unlink( $temp_file );
+	}
+
+	/**
+	 * Test rotating image on upload to normalise image orientation
+	 *
+	 * @ticket       14459
+	 *
+	 * @dataProvider get_images
+	 */
+	public function test_rotate_on_upload( $file ) {
+
+		preg_match( '/-(\d)\.(?:jpe?g|png|gif)$/', $file, $matches );
+		$orientation_value = intval( $matches[1] );
+
+		$image_id   = self::factory()->attachment->create_upload_object( $file );
+		$image_file = get_attached_file( $image_id );
+		$data       = wp_read_image_metadata( $image_file );
+
+		if ( in_array( $orientation_value, array( 3, 5, 8 ), true ) ) {
+			$this->assertEquals( 1, intval( $data['orientation'] ), 'Orientation exif data was not updated after uploading image: ' . $file );
+		} else {
+			$this->assertEquals( $orientation_value, intval( $data['orientation'] ), 'Orientation exif data was incorrectly modified after uploading image: ' . $file );
+		}
+
+	}
+
+	/**
+	 * dataProvider for images
+	 */
+	public function get_images() {
+		return array_map( function ( $num ) {
+			return array( DIR_TESTDATA . "/images/orientation-{$num}.jpg" );
+		}, range( 1, 8 ) );
+	}
+
+	/**
+	 * Make a temporary copy of the image with an edit hash.
+	 *
+	 * @param $file
+	 * @param $modifier
+	 * @return string
+	 */
+	protected function get_temp_edited_image( $file, $modifier = '' ) {
+		$tmp_file = wp_tempnam( basename( $file ) ) . '-e1234567890123.jpg';
+		copy( $file, $tmp_file );
+		return $tmp_file;
+	}
+
+}
