diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-admin/includes/image.php --- a/wp/wp-admin/includes/image.php Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-admin/includes/image.php Fri Sep 05 18:52:52 2025 +0200 @@ -261,101 +261,128 @@ $image_meta['image_meta'] = $exif_meta; } - // Do not scale (large) PNG images. May result in sub-sizes that have greater file size than the original. See #48736. - if ( 'image/png' !== $imagesize['mime'] ) { + /** + * Filters the "BIG image" threshold value. + * + * If the original image width or height is above the threshold, it will be scaled down. The threshold is + * used as max width and max height. The scaled down image will be used as the largest available size, including + * the `_wp_attached_file` post meta value. + * + * Returning `false` from the filter callback will disable the scaling. + * + * @since 5.3.0 + * + * @param int $threshold The threshold value in pixels. Default 2560. + * @param array $imagesize { + * Indexed array of the image width and height in pixels. + * + * @type int $0 The image width. + * @type int $1 The image height. + * } + * @param string $file Full path to the uploaded image file. + * @param int $attachment_id Attachment post ID. + */ + $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id ); + + /* + * If the original image's dimensions are over the threshold, + * scale the image and use it as the "full" size. + */ + $scale_down = false; + $convert = false; + + if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) { + // The image will be converted if needed on saving. + $scale_down = true; + } else { + // The image may need to be converted regardless of its dimensions. + $output_format = wp_get_image_editor_output_format( $file, $imagesize['mime'] ); - /** - * Filters the "BIG image" threshold value. - * - * If the original image width or height is above the threshold, it will be scaled down. The threshold is - * used as max width and max height. The scaled down image will be used as the largest available size, including - * the `_wp_attached_file` post meta value. - * - * Returning `false` from the filter callback will disable the scaling. - * - * @since 5.3.0 - * - * @param int $threshold The threshold value in pixels. Default 2560. - * @param array $imagesize { - * Indexed array of the image width and height in pixels. - * - * @type int $0 The image width. - * @type int $1 The image height. - * } - * @param string $file Full path to the uploaded image file. - * @param int $attachment_id Attachment post ID. - */ - $threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id ); + if ( + is_array( $output_format ) && + array_key_exists( $imagesize['mime'], $output_format ) && + $output_format[ $imagesize['mime'] ] !== $imagesize['mime'] + ) { + $convert = true; + } + } + + if ( $scale_down || $convert ) { + $editor = wp_get_image_editor( $file ); + + if ( is_wp_error( $editor ) ) { + // This image cannot be edited. + return $image_meta; + } - /* - * If the original image's dimensions are over the threshold, - * scale the image and use it as the "full" size. - */ - if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) { - $editor = wp_get_image_editor( $file ); + if ( $scale_down ) { + // Resize the image. This will also convet it if needed. + $resized = $editor->resize( $threshold, $threshold ); + } elseif ( $convert ) { + // The image will be converted (if possible) when saved. + $resized = true; + } + + $rotated = null; - if ( is_wp_error( $editor ) ) { - // This image cannot be edited. - return $image_meta; + // If there is EXIF data, rotate according to EXIF Orientation. + if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) { + $resized = $editor->maybe_exif_rotate(); + $rotated = $resized; // bool true or WP_Error + } + + if ( ! is_wp_error( $resized ) ) { + /* + * Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg". + * This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). + */ + if ( $scale_down ) { + $saved = $editor->save( $editor->generate_filename( 'scaled' ) ); + } elseif ( $convert ) { + // Pass an empty string to avoid adding a suffix to converted file names. + $saved = $editor->save( $editor->generate_filename( '' ) ); + } else { + $saved = $editor->save(); } - // Resize the image. - $resized = $editor->resize( $threshold, $threshold ); - $rotated = null; - - // If there is EXIF data, rotate according to EXIF Orientation. - if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) { - $resized = $editor->maybe_exif_rotate(); - $rotated = $resized; - } + if ( ! is_wp_error( $saved ) ) { + $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); - if ( ! is_wp_error( $resized ) ) { - /* - * Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg". - * This doesn't affect the sub-sizes names as they are generated from the original image (for best quality). - */ - $saved = $editor->save( $editor->generate_filename( 'scaled' ) ); - - if ( ! is_wp_error( $saved ) ) { - $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); - - // If the image was rotated update the stored EXIF data. - if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) { - $image_meta['image_meta']['orientation'] = 1; - } - } else { - // TODO: Log errors. + // If the image was rotated update the stored EXIF data. + if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) { + $image_meta['image_meta']['orientation'] = 1; } } else { // TODO: Log errors. } - } elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) { - // Rotate the whole original image if there is EXIF data and "orientation" is not 1. - - $editor = wp_get_image_editor( $file ); + } else { + // TODO: Log errors. + } + } elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) { + // Rotate the whole original image if there is EXIF data and "orientation" is not 1. + $editor = wp_get_image_editor( $file ); - if ( is_wp_error( $editor ) ) { - // This image cannot be edited. - return $image_meta; - } - - // Rotate the image. - $rotated = $editor->maybe_exif_rotate(); + if ( is_wp_error( $editor ) ) { + // This image cannot be edited. + return $image_meta; + } - if ( true === $rotated ) { - // Append `-rotated` to the image file name. - $saved = $editor->save( $editor->generate_filename( 'rotated' ) ); + // Rotate the image. + $rotated = $editor->maybe_exif_rotate(); - if ( ! is_wp_error( $saved ) ) { - $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); + if ( true === $rotated ) { + // Append `-rotated` to the image file name. + $saved = $editor->save( $editor->generate_filename( 'rotated' ) ); - // Update the stored EXIF data. - if ( ! empty( $image_meta['image_meta']['orientation'] ) ) { - $image_meta['image_meta']['orientation'] = 1; - } - } else { - // TODO: Log errors. + if ( ! is_wp_error( $saved ) ) { + $image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id ); + + // Update the stored EXIF data. + if ( ! empty( $image_meta['image_meta']['orientation'] ) ) { + $image_meta['image_meta']['orientation'] = 1; } + } else { + // TODO: Log errors. } } } @@ -543,6 +570,7 @@ * * @since 2.1.0 * @since 6.0.0 The `$filesize` value was added to the returned array. + * @since 6.7.0 The 'image/heic' mime type is supported. * * @param int $attachment_id Attachment ID to process. * @param string $file Filepath of the attached image. @@ -555,7 +583,7 @@ $support = false; $mime_type = get_post_mime_type( $attachment ); - if ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) { + if ( 'image/heic' === $mime_type || ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) ) { // Make thumbnails and other intermediate sizes. $metadata = wp_create_image_subsizes( $file, $attachment_id ); } elseif ( wp_attachment_is( 'video', $attachment ) ) {