Skip to content

API for mime type in add_image_size, filtering mime output by image size, enable for core sizes #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: add/webp-uploads
Choose a base branch
from
46 changes: 37 additions & 9 deletions src/wp-admin/includes/image.php
Original file line number Diff line number Diff line change
Expand Up @@ -505,13 +505,20 @@ function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mim
return array();
}

$original_mime_type = wp_get_image_mime( $file );

if ( ! $mime_type ) {
$mime_type = wp_get_image_mime( $file );
$mime_type = $original_mime_type;
}

// Check if any of the new sizes already exist.
if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
// Check if the output mime is enabled for this image size.
if ( ! _wp_mime_type_available_for_image_size( $attachment_id, $size_name, $original_mime_type, $mime_type ) ) {
continue;
}

/*
* Only checks "size name" so we don't override existing images even if the dimensions
* don't match the currently defined size with the same name.
Expand Down Expand Up @@ -605,6 +612,21 @@ function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id, $mim
return $image_meta;
}

/**
* Check whether mime type output is available for a given size and mime type.
*
* @since 6.1.0
*
* @param int $attachment_id Attachment ID.
* @param string $size_name Size name to check.
* @return bool Whether the size is available for the given mime type.
*/
function _wp_mime_type_available_for_image_size( $attachment_id, $size_name, $source_mime, $destination_mime ) {
$image_mime_transforms = wp_upload_image_mime_transforms( $attachment_id, $size_name );

return isset( $image_mime_transforms[ $source_mime ] [ $destination_mime ] ) && image_size_supports_mime( $size_name, $destination_mime );
}

/**
* Low-level function to create full-size images in additional mime types.
*
Expand Down Expand Up @@ -1336,28 +1358,34 @@ function _copy_image_file( $attachment_id ) {
* For example an `image/jpeg` should be converted into an `image/jpeg` and `image/webp`. The first type
* is considered the primary output type for this image.
*
* Called for each uploaded image to determine the list of mime types that should be converted into. Then,
* called again for each target image size as they are generated to see if the image should be converted into the mime type
* for that size.
*
* @since 6.1.0
*
* @param $attachment_id int The attachment ID.
* @param int $attachment_id The attachment ID.
* @param string $image_size The image size name. False when called on the image and target size is unavailable.
* @return array An array of valid mime types, where the key is the source file mime type and the list of mime types to
* generate.
*/
function wp_upload_image_mime_transforms( $attachment_id ) {
function wp_upload_image_mime_transforms( $attachment_id, $image_size ) {
$image_mime_transforms = array(
'image/jpeg' => array( 'image/jpeg', 'image/webp' ),
'image/webp' => array( 'image/webp', 'image/jpeg' ),
);

/**
* Filter to the output mime types for a given input mime type.
* Filter to the output mime types for a given input mime type and image size.
*
* @since 6.1.0
*
* @param array $image_mime_transforms A map with the valid mime transforms where the key is the source file mime type
* and the value is one or more mime file types to generate.
* @param int $attachment_id The ID of the attachment where the hook was dispatched.
* @param array $image_mime_transforms A map with the valid mime transforms where the key is the source file mime type
* and the value is one or more mime file types to generate.
* @param int $attachment_id The ID of the attachment where the hook was dispatched.
* @param string $image_size The image size name. Optional.
*/
return (array) apply_filters( 'wp_upload_image_mime_transforms', $image_mime_transforms, $attachment_id );
return (array) apply_filters( 'wp_upload_image_mime_transforms', $image_mime_transforms, $attachment_id, $image_size );
}

/**
Expand All @@ -1371,7 +1399,7 @@ function wp_upload_image_mime_transforms( $attachment_id ) {
* @return array An array with two entries, the primary mime type and the list of additional mime types.
*/
function _wp_get_primary_and_additional_mime_types( $file, $attachment_id ) {
$image_mime_transforms = wp_upload_image_mime_transforms( $attachment_id );
$image_mime_transforms = wp_upload_image_mime_transforms( $attachment_id, false );
$original_mime_type = wp_get_image_mime( $file );
$output_mime_types = isset( $image_mime_transforms[ $original_mime_type ] ) ? $image_mime_transforms[ $original_mime_type ] : array( $original_mime_type );

Expand Down
4 changes: 2 additions & 2 deletions src/wp-content/themes/twentyeleven/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ function twentyeleven_setup() {
* Add Twenty Eleven's custom image sizes.
* Used for large feature (header) images.
*/
add_image_size( 'large-feature', $custom_header_support['width'], $custom_header_support['height'], true );
add_image_size( 'large-feature', $custom_header_support['width'], $custom_header_support['height'], true, true );
// Used for featured posts if a large-feature doesn't exist.
add_image_size( 'small-feature', 500, 300 );
add_image_size( 'small-feature', 500, 300, false, true );

// Default custom headers packaged with the theme. %s is a placeholder for the theme template directory URI.
register_default_headers(
Expand Down
2 changes: 1 addition & 1 deletion src/wp-content/themes/twentyfourteen/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function twentyfourteen_setup() {
// Enable support for Post Thumbnails, and declare two sizes.
add_theme_support( 'post-thumbnails' );
set_post_thumbnail_size( 672, 372, true );
add_image_size( 'twentyfourteen-full-width', 1038, 576, true );
add_image_size( 'twentyfourteen-full-width', 1038, 576, true, true );

// This theme uses wp_nav_menu() in two locations.
register_nav_menus(
Expand Down
4 changes: 2 additions & 2 deletions src/wp-content/themes/twentyseventeen/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ function twentyseventeen_setup() {
*/
add_theme_support( 'post-thumbnails' );

add_image_size( 'twentyseventeen-featured-image', 2000, 1200, true );
add_image_size( 'twentyseventeen-featured-image', 2000, 1200, true, true );

add_image_size( 'twentyseventeen-thumbnail-avatar', 100, 100, true );
add_image_size( 'twentyseventeen-thumbnail-avatar', 100, 100, true, true );

// Set the default content width.
$GLOBALS['content_width'] = 525;
Expand Down
2 changes: 1 addition & 1 deletion src/wp-content/themes/twentytwenty/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function twentytwenty_theme_support() {
set_post_thumbnail_size( 1200, 9999 );

// Add custom image size used in Cover Template.
add_image_size( 'twentytwenty-fullscreen', 1980, 9999 );
add_image_size( 'twentytwenty-fullscreen', 1980, 9999, false, true );

// Custom logo.
$logo_width = 120;
Expand Down
72 changes: 51 additions & 21 deletions src/wp-includes/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,29 +275,55 @@ function image_downsize( $id, $size = 'medium' ) {
* Register a new image size.
*
* @since 2.9.0
* @since 6.1.0 Add the $output_mimes parameter.
*
* @global array $_wp_additional_image_sizes Associative array of additional image sizes.
*
* @param string $name Image size identifier.
* @param int $width Optional. Image width in pixels. Default 0.
* @param int $height Optional. Image height in pixels. Default 0.
* @param bool|array $crop Optional. Image cropping behavior. If false, the image will be scaled (default),
* If true, image will be cropped to the specified dimensions using center positions.
* If an array, the image will be cropped using the array to specify the crop location.
* Array values must be in the format: array( x_crop_position, y_crop_position ) where:
* - x_crop_position accepts: 'left', 'center', or 'right'.
* - y_crop_position accepts: 'top', 'center', or 'bottom'.
* @param string $name Image size identifier.
* @param int $width Optional. Image width in pixels. Default 0.
* @param int $height Optional. Image height in pixels. Default 0.
* @param bool|array $crop Optional. Image cropping behavior. If false, the image will be scaled (default),
* If true, image will be cropped to the specified dimensions using center positions.
* If an array, the image will be cropped using the array to specify the crop location.
* Array values must be in the format: array( x_crop_position, y_crop_position ) where:
* - x_crop_position accepts: 'left', 'center', or 'right'.
* - y_crop_position accepts: 'top', 'center', or 'bottom'.
* @param bool $output_mimes Whether to output secondary mimes for this image size. Default is null which will
* throw a doing_it_wrong warning to warn developers they should set this value.
* Default will be true in 6.2.
*/
function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
function add_image_size( $name, $width = 0, $height = 0, $crop = false, $output_mimes = null ) {
global $_wp_additional_image_sizes;

// For 6.1.x, warn developers about setting a value for $output_mimes.
if ( null === $output_mimes ) {
_doing_it_wrong( __FUNCTION__, __( 'Passing the $output_mimes parameter to add_image_size is recommended.' ), '6.1.0' );
}

$_wp_additional_image_sizes[ $name ] = array(
'width' => absint( $width ),
'height' => absint( $height ),
'crop' => $crop,
'width' => absint( $width ),
'height' => absint( $height ),
'crop' => $crop,
'output_mimes' => $output_mimes,
);
}

/**
* Check if an image size supports output in a specific mime type.
*
* @since 6.1.0
*
* @uses wp_get_additional_image_sizes()
*
* @param string $name Image size identifier.
* @param string $mime_type The mime type to check.
* @return bool Whether the size supports the mime type for output.
*/
function image_size_supports_mime( $name, $mime_type ) {
$sizes = wp_get_additional_image_sizes();
return isset( $sizes[ $name ]['output_mimes'] ) && $sizes[ $name ]['output_mimes'];
}

/**
* Check if an image size exists.
*
Expand Down Expand Up @@ -345,7 +371,7 @@ function remove_image_size( $name ) {
* An array can specify positioning of the crop area. Default false.
*/
function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
add_image_size( 'post-thumbnail', $width, $height, $crop );
add_image_size( 'post-thumbnail', $width, $height, $crop, true );
}

/**
Expand Down Expand Up @@ -890,11 +916,15 @@ function wp_get_registered_image_subsizes() {
$all_sizes = array();

foreach ( get_intermediate_image_sizes() as $size_name ) {
$size_data = array(
'width' => 0,
'height' => 0,
'crop' => false,
);
$default_sizes = array( 'thumbnail', 'medium', 'medium_large', 'large' );
foreach ( get_intermediate_image_sizes() as $size_name ) {
$size_data = array(
'width' => 0,
'height' => 0,
'crop' => false,
'output_mimes' => in_array( $size_name, $default_sizes, true ),
);
}

if ( isset( $additional_sizes[ $size_name ]['width'] ) ) {
// For sizes added by plugins and themes.
Expand Down Expand Up @@ -5292,9 +5322,9 @@ function wp_media_personal_data_exporter( $email_address, $page = 1 ) {
*/
function _wp_add_additional_image_sizes() {
// 2x medium_large size.
add_image_size( '1536x1536', 1536, 1536 );
add_image_size( '1536x1536', 1536, 1536, false, true );
// 2x large size.
add_image_size( '2048x2048', 2048, 2048 );
add_image_size( '2048x2048', 2048, 2048, false, true );
}

/**
Expand Down
15 changes: 15 additions & 0 deletions tests/phpunit/tests/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,21 @@ public function test_has_image_size() {
remove_image_size( 'test-size' );
}

/**
* @ticket 55443
*/
public function test_image_size_supports_mime() {
add_image_size( 'test-size', 200, 600, true, false );
$this->assertSame( false, image_size_supports_mime( 'test-size', 'image/webp' ) );
remove_image_size( 'test-size' );

add_image_size( 'test-size', 200, 600, true, true );
$this->assertSame( true, image_size_supports_mime( 'test-size', 'image/webp' ) );

// Clean up.
remove_image_size( 'test-size' );
}

/**
* @ticket 30346
*/
Expand Down