Media: Automatically convert HEIC images to JPEG
Automatically create a JPEG version of uploaded HEIC images if the server has a version of Imagick that supports HEIC. Conversion is done silently through the existing `WP_Image_Editor` infrastructure that creates multiple sizes of uploaded images. This allows users to view HEIC images in WP Admin and use them in their posts and pages regardless of whether their browser supports HEIC. Browser support for HEIC is relatively low (only Safari) while the occurrence of HEIC images is relatively common. The original HEIC image can be downloaded via a link on the attachment page. Props adamsilverstein, noisysocks, swissspidy, spacedmonkey, peterwilsoncc. Fixes #53645. Built from https://develop.svn.wordpress.org/trunk@58849 git-svn-id: http://core.svn.wordpress.org/trunk@58245 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
066d83f670
commit
3a703f86cd
|
@ -543,6 +543,7 @@ function wp_copy_parent_attachment_properties( $cropped, $parent_attachment_id,
|
|||
*
|
||||
* @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 +556,7 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
|
|||
$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 ) ) {
|
||||
|
|
|
@ -219,7 +219,6 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
|
|||
$this->image->setImageCompressionQuality( $quality );
|
||||
}
|
||||
break;
|
||||
case 'image/avif':
|
||||
default:
|
||||
$this->image->setImageCompressionQuality( $quality );
|
||||
}
|
||||
|
@ -258,10 +257,10 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
|
|||
}
|
||||
|
||||
/*
|
||||
* If we still don't have the image size, fall back to `wp_getimagesize`. This ensures AVIF images
|
||||
* If we still don't have the image size, fall back to `wp_getimagesize`. This ensures AVIF and HEIC images
|
||||
* are properly sized without affecting previous `getImageGeometry` behavior.
|
||||
*/
|
||||
if ( ( ! $width || ! $height ) && 'image/avif' === $this->mime_type ) {
|
||||
if ( ( ! $width || ! $height ) && ( 'image/avif' === $this->mime_type || 'image/heic' === $this->mime_type ) ) {
|
||||
$size = wp_getimagesize( $this->file );
|
||||
$width = $size[0];
|
||||
$height = $size[1];
|
||||
|
|
|
@ -318,7 +318,6 @@ abstract class WP_Image_Editor {
|
|||
$quality = 86;
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
case 'image/avif':
|
||||
default:
|
||||
$quality = $this->default_quality;
|
||||
}
|
||||
|
@ -366,26 +365,7 @@ abstract class WP_Image_Editor {
|
|||
$new_ext = $file_ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the image editor output format mapping.
|
||||
*
|
||||
* Enables filtering the mime type used to save images. By default,
|
||||
* the mapping array is empty, so the mime type matches the source image.
|
||||
*
|
||||
* @see WP_Image_Editor::get_output_format()
|
||||
*
|
||||
* @since 5.8.0
|
||||
*
|
||||
* @param string[] $output_format {
|
||||
* An array of mime type mappings. Maps a source mime type to a new
|
||||
* destination mime type. Default empty array.
|
||||
*
|
||||
* @type string ...$0 The new mime type.
|
||||
* }
|
||||
* @param string $filename Path to the image.
|
||||
* @param string $mime_type The source image mime type.
|
||||
*/
|
||||
$output_format = apply_filters( 'image_editor_output_format', array(), $filename, $mime_type );
|
||||
$output_format = wp_get_image_editor_output_format( $filename, $mime_type );
|
||||
|
||||
if ( isset( $output_format[ $mime_type ] )
|
||||
&& $this->supports_mime_type( $output_format[ $mime_type ] )
|
||||
|
|
|
@ -549,3 +549,8 @@ if ( ! defined( 'IMAGETYPE_AVIF' ) ) {
|
|||
if ( ! defined( 'IMG_AVIF' ) ) {
|
||||
define( 'IMG_AVIF', IMAGETYPE_AVIF );
|
||||
}
|
||||
|
||||
// IMAGETYPE_HEIC constant is not yet defined in PHP as of PHP 8.3.
|
||||
if ( ! defined( 'IMAGETYPE_HEIC' ) ) {
|
||||
define( 'IMAGETYPE_HEIC', 99 );
|
||||
}
|
||||
|
|
|
@ -2706,8 +2706,7 @@ function wp_unique_filename( $dir, $filename, $unique_filename_callback = null )
|
|||
* when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes.
|
||||
*/
|
||||
if ( $is_image ) {
|
||||
/** This filter is documented in wp-includes/class-wp-image-editor.php */
|
||||
$output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type );
|
||||
$output_formats = wp_get_image_editor_output_format( $_dir . $filename, $mime_type );
|
||||
$alt_types = array();
|
||||
|
||||
if ( ! empty( $output_formats[ $mime_type ] ) ) {
|
||||
|
@ -3120,6 +3119,7 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
|
|||
'image/tiff' => 'tif',
|
||||
'image/webp' => 'webp',
|
||||
'image/avif' => 'avif',
|
||||
'image/heic' => 'heic',
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -3299,6 +3299,7 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
|
|||
* @since 4.7.1
|
||||
* @since 5.8.0 Added support for WebP images.
|
||||
* @since 6.5.0 Added support for AVIF images.
|
||||
* @since 6.7.0 Added support for HEIC images.
|
||||
*
|
||||
* @param string $file Full path to the file.
|
||||
* @return string|false The actual mime type or false if the type cannot be determined.
|
||||
|
@ -3372,6 +3373,15 @@ function wp_get_image_mime( $file ) {
|
|||
) {
|
||||
$mime = 'image/avif';
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $magic[1] ) &&
|
||||
isset( $magic[2] ) &&
|
||||
'ftyp' === hex2bin( $magic[1] ) &&
|
||||
( 'heic' === hex2bin( $magic[2] ) || 'heif' === hex2bin( $magic[2] ) )
|
||||
) {
|
||||
$mime = 'image/heic';
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$mime = false;
|
||||
}
|
||||
|
|
|
@ -1449,7 +1449,7 @@ Library = wp.media.controller.State.extend(/** @lends wp.media.controller.Librar
|
|||
isImageAttachment: function( attachment ) {
|
||||
// If uploading, we know the filename but not the mime type.
|
||||
if ( attachment.get('uploading') ) {
|
||||
return /\.(jpe?g|png|gif|webp|avif)$/i.test( attachment.get('filename') );
|
||||
return /\.(jpe?g|png|gif|webp|avif|heic)$/i.test( attachment.get('filename') );
|
||||
}
|
||||
|
||||
return attachment.get('type') === 'image';
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4064,8 +4064,7 @@ function wp_get_image_editor( $path, $args = array() ) {
|
|||
|
||||
// Check and set the output mime type mapped to the input type.
|
||||
if ( isset( $args['mime_type'] ) ) {
|
||||
/** This filter is documented in wp-includes/class-wp-image-editor.php */
|
||||
$output_format = apply_filters( 'image_editor_output_format', array(), $path, $args['mime_type'] );
|
||||
$output_format = wp_get_image_editor_output_format( $path, $args['mime_type'] );
|
||||
if ( isset( $output_format[ $args['mime_type'] ] ) ) {
|
||||
$args['output_mime_type'] = $output_format[ $args['mime_type'] ];
|
||||
}
|
||||
|
@ -4224,6 +4223,11 @@ function wp_plupload_default_settings() {
|
|||
$defaults['avif_upload_error'] = true;
|
||||
}
|
||||
|
||||
// Check if HEIC images can be edited.
|
||||
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/heic' ) ) ) {
|
||||
$defaults['heic_upload_error'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the Plupload default settings.
|
||||
*
|
||||
|
@ -5483,12 +5487,17 @@ function _wp_add_additional_image_sizes() {
|
|||
* Callback to enable showing of the user error when uploading .heic images.
|
||||
*
|
||||
* @since 5.5.0
|
||||
* @since 6.7.0 The default behavior is to enable heic uplooads as long as the server
|
||||
* supports the format. The uploads are converted to JPEG's by default.
|
||||
*
|
||||
* @param array[] $plupload_settings The settings for Plupload.js.
|
||||
* @return array[] Modified settings for Plupload.js.
|
||||
*/
|
||||
function wp_show_heic_upload_error( $plupload_settings ) {
|
||||
$plupload_settings['heic_upload_error'] = true;
|
||||
// Check if HEIC images can be edited.
|
||||
if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/heic' ) ) ) {
|
||||
$plupload_init['heic_upload_error'] = true;
|
||||
}
|
||||
return $plupload_settings;
|
||||
}
|
||||
|
||||
|
@ -5586,6 +5595,29 @@ function wp_getimagesize( $filename, ?array &$image_info = null ) {
|
|||
}
|
||||
}
|
||||
|
||||
// For PHP versions that don't support HEIC images, extract the size info using Imagick when available.
|
||||
if ( 'image/heic' === wp_get_image_mime( $filename ) ) {
|
||||
$editor = wp_get_image_editor( $filename );
|
||||
if ( is_wp_error( $editor ) ) {
|
||||
return false;
|
||||
}
|
||||
// If the editor for HEICs is Imagick, use it to get the image size.
|
||||
if ( $editor instanceof WP_Image_Editor_Imagick ) {
|
||||
$size = $editor->get_size();
|
||||
return array(
|
||||
$size['width'],
|
||||
$size['height'],
|
||||
IMAGETYPE_HEIC,
|
||||
sprintf(
|
||||
'width="%d" height="%d"',
|
||||
$size['width'],
|
||||
$size['height']
|
||||
),
|
||||
'mime' => 'image/heic',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The image could not be parsed.
|
||||
return false;
|
||||
}
|
||||
|
@ -6069,3 +6101,37 @@ function wp_high_priority_element_flag( $value = null ) {
|
|||
|
||||
return $high_priority_element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the output format for the image editor.
|
||||
*
|
||||
* @since 6.7.0
|
||||
* @access private
|
||||
*
|
||||
* @param string $filename Path to the image.
|
||||
* @param string $mime_type The source image mime type.
|
||||
* @return string[] An array of mime type mappings.
|
||||
*/
|
||||
function wp_get_image_editor_output_format( $filename, $mime_type ) {
|
||||
/**
|
||||
* Filters the image editor output format mapping.
|
||||
*
|
||||
* Enables filtering the mime type used to save images. By default,
|
||||
* the mapping array is empty, so the mime type matches the source image.
|
||||
*
|
||||
* @see WP_Image_Editor::get_output_format()
|
||||
*
|
||||
* @since 5.8.0
|
||||
* @since 6.7.0 The default was changed from array() to array( 'image/heic' => 'image/jpeg' ).
|
||||
*
|
||||
* @param string[] $output_format {
|
||||
* An array of mime type mappings. Maps a source mime type to a new
|
||||
* destination mime type. Default maps uploaded HEIC images to JPEG output.
|
||||
*
|
||||
* @type string ...$0 The new mime type.
|
||||
* }
|
||||
* @param string $filename Path to the image.
|
||||
* @param string $mime_type The source image mime type.
|
||||
*/
|
||||
return apply_filters( 'image_editor_output_format', array( 'image/heic' => 'image/jpeg' ), $filename, $mime_type );
|
||||
}
|
||||
|
|
|
@ -6829,7 +6829,7 @@ function wp_attachment_is( $type, $post = null ) {
|
|||
|
||||
switch ( $type ) {
|
||||
case 'image':
|
||||
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp', 'avif' );
|
||||
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp', 'avif', 'heic' );
|
||||
return in_array( $ext, $image_exts, true );
|
||||
|
||||
case 'audio':
|
||||
|
|
|
@ -531,7 +531,7 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|||
);
|
||||
}
|
||||
|
||||
$supported_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif' );
|
||||
$supported_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif', 'image/heic' );
|
||||
$mime_type = get_post_mime_type( $attachment_id );
|
||||
if ( ! in_array( $mime_type, $supported_types, true ) ) {
|
||||
return new WP_Error(
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '6.7-alpha-58848';
|
||||
$wp_version = '6.7-alpha-58849';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
Loading…
Reference in New Issue