Make WordPress Core


Ignore:
Timestamp:
09/20/2019 06:20:26 PM (5 years ago)
Author:
azaozz
Message:

Media/Upload: rotate images on upload according to EXIF Orientation.

Props msaggiorato, wpdavis, markoheijnen, dhuyvetter, msaggiorato, n7studios, triplejumper12, pbiron, mikeschroder, joemcgill, azaozz.

Fixes #14459.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/image.php

    r46076 r46202  
    160160
    161161/**
     162 * Updates the attached file and image meta data when the original image was edited.
     163 *
     164 * @since 5.3.0
     165 * @access private
     166 *
     167 * @param array  $saved_data    The data retirned from WP_Image_Editor after successfully saving an image.
     168 * @param string $original_file Path to the original file.
     169 * @param array  $image_meta    The image meta data.
     170 * @param int    $attachment_id The attachment post ID.
     171 * @return array The updated image meta data.
     172 */
     173function _wp_image_meta_replace_original( $saved_data, $original_file, $image_meta, $attachment_id ) {
     174    $new_file = $saved_data['path'];
     175
     176    // Update the attached file meta.
     177    update_attached_file( $attachment_id, $new_file );
     178
     179    // Width and height of the new image.
     180    $image_meta['width']  = $saved_data['width'];
     181    $image_meta['height'] = $saved_data['height'];
     182
     183    // Make the file path relative to the upload dir.
     184    $image_meta['file'] = _wp_relative_upload_path( $new_file );
     185
     186    // Store the original image file name in image_meta.
     187    $image_meta['original_image'] = wp_basename( $original_file );
     188
     189    return $image_meta;
     190}
     191
     192/**
    162193 * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
    163194 *
     
    223254        // Resize the image
    224255        $resized = $editor->resize( $threshold, $threshold );
     256        $rotated = null;
     257
     258        // If there is EXIF data, rotate according to EXIF Orientation.
     259        if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
     260            $resized = $editor->maybe_exif_rotate();
     261            $rotated = $resized;
     262        }
    225263
    226264        if ( ! is_wp_error( $resized ) ) {
    227             // TODO: EXIF rotate here.
    228             // By default the editor will append `{width}x{height}` to the file name of the resized image.
    229             // Better to append the threshold size instead so the image file name would be like "my-image-2560.jpg"
    230             // and not look like a "regular" sub-size.
     265            // Append the threshold size to the image file name. It will look like "my-image-2560.jpg".
    231266            // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
    232267            $saved = $editor->save( $editor->generate_filename( $threshold ) );
    233268
    234269            if ( ! is_wp_error( $saved ) ) {
    235                 $new_file = $saved['path'];
    236 
    237                 // Update the attached file meta.
    238                 update_attached_file( $attachment_id, $new_file );
    239 
    240                 // Width and height of the new image.
    241                 $image_meta['width']  = $saved['width'];
    242                 $image_meta['height'] = $saved['height'];
    243 
    244                 // Make the file path relative to the upload dir.
    245                 $image_meta['file'] = _wp_relative_upload_path( $new_file );
    246 
    247                 // Store the original image file name in image_meta.
    248                 $image_meta['original_image'] = wp_basename( $file );
     270                $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
     271
     272                // If the image was rotated update the stored EXIF data.
     273                if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
     274                    $image_meta['image_meta']['orientation'] = 1;
     275                }
     276            } else {
     277                // TODO: handle errors.
     278            }
     279        } else {
     280            // TODO: handle errors.
     281        }
     282    } elseif ( ! empty( $exif_meta['orientation'] ) && (int) $exif_meta['orientation'] !== 1 ) {
     283        // Rotate the whole original image if there is EXIF data and "orientation" is not 1.
     284
     285        $editor = wp_get_image_editor( $file );
     286
     287        if ( is_wp_error( $editor ) ) {
     288            // This image cannot be edited.
     289            return $image_meta;
     290        }
     291
     292        // Rotate the image
     293        $rotated = $editor->maybe_exif_rotate();
     294
     295        if ( true === $rotated ) {
     296            // Append `-rotated` to the image file name.
     297            $saved = $editor->save( $editor->generate_filename( 'rotated' ) );
     298
     299            if ( ! is_wp_error( $saved ) ) {
     300                $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );
     301
     302                // Update the stored EXIF data.
     303                if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
     304                    $image_meta['image_meta']['orientation'] = 1;
     305                }
     306            } else {
     307                // TODO: handle errors.
    249308            }
    250309        }
     
    326385        // The image cannot be edited.
    327386        return $image_meta;
     387    }
     388
     389    // If stored EXIF data exists, rotate the source image before creating sub-sizes.
     390    if ( ! empty( $image_meta['image_meta'] ) ) {
     391        $rotated = $editor->maybe_exif_rotate();
     392
     393        if ( is_wp_error( $rotated ) ) {
     394            // TODO: handle errors.
     395        }
    328396    }
    329397
Note: See TracChangeset for help on using the changeset viewer.