Ticket #14459: 14459.4.diff
File 14459.4.diff, 8.5 KB (added by , 5 years ago) |
---|
-
src/wp-admin/includes/image.php
159 159 } 160 160 161 161 /** 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 */ 173 function _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 /** 162 193 * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata. 163 194 * 164 195 * Intended for use after an image is uploaded. Saves/updates the image metadata after each … … 223 254 // Resize the image 224 255 $resized = $editor->resize( $threshold, $threshold ); 225 256 257 // Rotate JPEGs according to EXIF Orientation. 258 if ( ! is_wp_error( $resized ) && ! empty( $exif_meta['orientation'] ) && (int) $exif_meta['orientation'] !== 1 ) { 259 $resized = $editor->maybe_exif_rotate(); 260 } 261 226 262 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. 263 // Append the threshold size to the image file name. It would be like "my-image-2560.jpg". 231 264 // This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). 232 265 $saved = $editor->save( $editor->generate_filename( $threshold ) ); 233 266 234 267 if ( ! is_wp_error( $saved ) ) { 235 $new_file = $saved['path']; 268 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); 269 } else { 270 // TODO: handle errors. 271 } 272 } else { 273 // TODO: handle errors. 274 } 275 } elseif ( ! empty( $exif_meta['orientation'] ) && (int) $exif_meta['orientation'] !== 1 ) { 276 $editor = wp_get_image_editor( $file ); 236 277 237 // Update the attached file meta. 238 update_attached_file( $attachment_id, $new_file ); 278 if ( is_wp_error( $editor ) ) { 279 // This image cannot be edited. 280 return $image_meta; 281 } 239 282 240 // Width and height of the new image. 241 $image_meta['width'] = $saved['width']; 242 $image_meta['height'] = $saved['height']; 283 // Rotate the image 284 $rotated = $editor->maybe_exif_rotate(); 243 285 244 // Make the file path relative to the upload dir. 245 $image_meta['file'] = _wp_relative_upload_path( $new_file ); 286 if ( true === $rotated ) { 287 // Append `-rotated` to the image file name. It would be like "my-image-rotated.jpg". 288 $saved = $editor->save( $editor->generate_filename( 'rotated' ) ); 246 289 247 // Store the original image file name in image_meta. 248 $image_meta['original_image'] = wp_basename( $file ); 290 if ( ! is_wp_error( $saved ) ) { 291 $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); 292 } else { 293 // TODO: handle errors. 249 294 } 250 295 } 251 296 } … … 327 372 return $image_meta; 328 373 } 329 374 375 // If JPEG and EXIF data exists, rotate the source image before creating sub-sizes. 376 if ( ! empty( $image_meta['image_meta']['orientation'] ) && (int) $image_meta['image_meta']['orientation'] !== 1 ) { 377 $rotated = $editor->maybe_exif_rotate(); 378 379 if ( is_wp_error( $rotated ) ) { 380 // TODO: handle errors. 381 } 382 } 383 330 384 if ( method_exists( $editor, 'make_subsize' ) ) { 331 385 foreach ( $new_sizes as $new_size_name => $new_size_data ) { 332 386 $new_size_meta = $editor->make_subsize( $new_size_data ); -
src/wp-includes/class-wp-image-editor-imagick.php
566 566 try { 567 567 $this->image->rotateImage( new ImagickPixel( 'none' ), 360 - $angle ); 568 568 569 // Normalise E xiforientation data so that display is consistent across devices.569 // Normalise EXIF orientation data so that display is consistent across devices. 570 570 if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) { 571 571 $this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT ); 572 572 } … … 602 602 if ( $vert ) { 603 603 $this->image->flopImage(); 604 604 } 605 606 // Normalise EXIF orientation data so that display is consistent across devices. 607 if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) { 608 $this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT ); 609 } 605 610 } catch ( Exception $e ) { 606 611 return new WP_Error( 'image_flip_error', $e->getMessage() ); 607 612 } 613 608 614 return true; 609 615 } 610 616 611 617 /** 618 * Check if a JPEG image has EXIF Orientation tag and rotate it if needed. 619 * 620 * As Imagick copies the EXIF data to the flipped/rotated image, proceed only 621 * if the EXIF Orientation tag can be reset afterwards. 622 * 623 * @since 5.3.0 624 * 625 * @return bool|WP_Error True if the image was rotated. False if no EXIF data or if the image doesn't need rotation. 626 * WP_Error if error while rotating. 627 */ 628 public function maybe_exif_rotate() { 629 if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) { 630 return parent::maybe_exif_rotate(); 631 } else { 632 return new WP_Error( 'write_exif_error', __( 'The image cannot be rotated because the embedded meta data cannot be updated.' ) ); 633 } 634 } 635 636 /** 612 637 * Saves current image to file. 613 638 * 614 639 * @since 3.5.0 -
src/wp-includes/class-wp-image-editor.php
385 385 } 386 386 387 387 /** 388 * Check if a JPEG image has EXIF Orientation tag and rotate it if needed. 389 * 390 * @since 5.3.0 391 * 392 * @return bool|WP_Error True if the image was rotated. False if no EXIF data or if the image doesn't need rotation. 393 * WP_Error if error while rotating. 394 */ 395 public function maybe_exif_rotate() { 396 $orientation = null; 397 398 if ( is_callable( 'exif_read_data' ) && 'image/jpeg' === $this->mime_type ) { 399 $exif = @exif_read_data( $this->file ); 400 401 if ( ! empty( $exif['Orientation'] ) ) { 402 $orientation = (int) $exif['Orientation']; 403 } 404 } 405 406 if ( ! $orientation || $orientation === 1 ) { 407 return false; 408 } 409 410 switch ( $orientation ) { 411 case 2: 412 // Flip horizontally. 413 $result = $this->flip( true, false ); 414 break; 415 case 3: 416 // Rotate 180 degrees or flip horizontally and vertically. 417 // Flipping seems to be faster/use less resources. 418 $result = $this->flip( true, true ); 419 break; 420 case 4: 421 // Flip vertically. 422 $result = $this->flip( false, true ); 423 break; 424 case 5: 425 // Rotate 90 degrees counter-clockwise and flip vertically. 426 $result = $this->rotate( 90 ); 427 428 if ( ! is_wp_error( $result ) ) { 429 $result = $this->flip( false, true ); 430 } 431 432 break; 433 case 6: 434 // Rotate 90 degrees clockwise (270 counter-clockwise). 435 $result = $this->rotate( 270 ); 436 break; 437 case 7: 438 // Rotate 90 degrees counter-clockwise and flip horizontally. 439 $result = $this->rotate( 90 ); 440 441 if ( ! is_wp_error( $result ) ) { 442 $result = $this->flip( true, false ); 443 } 444 445 break; 446 case 8: 447 // Rotate 90 degrees counter-clockwise. 448 $result = $this->rotate( 90 ); 449 break; 450 } 451 452 return $result; 453 } 454 455 /** 388 456 * Either calls editor's save function or handles file as a stream. 389 457 * 390 458 * @since 3.5.0