Images: enable WebP support.

Add support for uploading, editing and saving WebP images when supported by the server.

Add 'image/webp' to supported mime types. Correctly identify WebP images and sizes even when PHP doesn't support WebP. Resize uploaded WebP files (when supported) and use for front end markup.

Props markoheijne, blobfolio, Clorith, joemcgill, atjn, desrosj, spacedmonkey, marylauc, mikeschroder, hellofromtonya, flixos90.
Fixes #35725.



git-svn-id: https://develop.svn.wordpress.org/trunk@50810 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Adam Silverstein
2021-05-04 14:43:36 +00:00
parent 80302b7b35
commit 6a5ff5aa03
24 changed files with 509 additions and 20 deletions

View File

@@ -306,6 +306,12 @@ function wp_stream_image( $image, $mime_type, $attachment_id ) {
case 'image/gif':
header( 'Content-Type: image/gif' );
return imagegif( $image );
case 'image/webp':
if ( function_exists( 'imagewebp' ) ) {
header( 'Content-Type: image/webp' );
return imagewebp( $image, null, 90 );
}
return false;
default:
return false;
}
@@ -391,6 +397,11 @@ function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
return imagepng( $image, $filename );
case 'image/gif':
return imagegif( $image, $filename );
case 'image/webp':
if ( function_exists( 'imagewebp' ) ) {
return imagewebp( $image, $filename );
}
return false;
default:
return false;
}

View File

@@ -517,6 +517,9 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
case 'image/png':
$ext = '.png';
break;
case 'image/webp':
$ext = '.webp';
break;
}
$basename = str_replace( '.', '-', wp_basename( $file ) ) . '-image' . $ext;
$uploaded = wp_upload_bits( $basename, '', $metadata['image']['data'] );
@@ -913,7 +916,7 @@ function file_is_valid_image( $path ) {
* @return bool True if suitable, false if not suitable.
*/
function file_is_displayable_image( $path ) {
$displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP, IMAGETYPE_ICO );
$displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP, IMAGETYPE_ICO, IMAGETYPE_WEBP ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.imagetype_webpFound
$info = wp_getimagesize( $path );
if ( empty( $info ) ) {
@@ -963,6 +966,12 @@ function load_image_to_edit( $attachment_id, $mime_type, $size = 'full' ) {
case 'image/gif':
$image = imagecreatefromgif( $filepath );
break;
case 'image/webp':
$image = false;
if ( function_exists( 'imagecreatefromwebp' ) ) {
$image = imagecreatefromwebp( $filepath );
}
break;
default:
$image = false;
break;

View File

@@ -993,7 +993,7 @@ function wp_media_upload_handler() {
function media_sideload_image( $file, $post_id = 0, $desc = null, $return = 'html' ) {
if ( ! empty( $file ) ) {
$allowed_extensions = array( 'jpg', 'jpeg', 'jpe', 'png', 'gif' );
$allowed_extensions = array( 'jpg', 'jpeg', 'jpe', 'png', 'gif', 'webp' );
/**
* Filters the list of allowed file extensions when sideloading an image from a URL.

View File

@@ -1215,6 +1215,7 @@ We hope you enjoy your new site. Thanks!
'jpeg',
'png',
'gif',
'webp',
// Video.
'mov',
'avi',

View File

@@ -69,6 +69,8 @@ class WP_Image_Editor_GD extends WP_Image_Editor {
return ( $image_types & IMG_PNG ) != 0;
case 'image/gif':
return ( $image_types & IMG_GIF ) != 0;
case 'image/webp':
return ( $image_types & IMG_WEBP ) != 0; // phpcs:ignore PHPCompatibility.Constants.NewConstants.img_webpFound
}
return false;
@@ -99,7 +101,15 @@ class WP_Image_Editor_GD extends WP_Image_Editor {
return new WP_Error( 'error_loading_image', __( 'File doesn’t exist?' ), $this->file );
}
$this->image = @imagecreatefromstring( $file_contents );
// WebP may not work with imagecreatefromstring().
if (
function_exists( 'imagecreatefromwebp' ) &&
( 'image/webp' === wp_get_image_mime( $this->file ) )
) {
$this->image = @imagecreatefromwebp( $this->file );
} else {
$this->image = @imagecreatefromstring( $file_contents );
}
if ( ! is_gd_image( $this->image ) ) {
return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file );
@@ -459,6 +469,10 @@ class WP_Image_Editor_GD extends WP_Image_Editor {
if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, $this->get_quality() ) ) ) {
return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
}
} elseif ( 'image/webp' == $mime_type ) {
if ( ! function_exists( 'imagewebp' ) || ! $this->make_image( $filename, 'imagewebp', array( $image, $filename, $this->get_quality() ) ) ) {
return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
}
} else {
return new WP_Error( 'image_save_error', __( 'Image Editor Save Failed' ) );
}
@@ -502,6 +516,12 @@ class WP_Image_Editor_GD extends WP_Image_Editor {
case 'image/gif':
header( 'Content-Type: image/gif' );
return imagegif( $this->image );
case 'image/webp':
if ( function_exists( 'imagewebp' ) ) {
header( 'Content-Type: image/webp' );
return imagewebp( $this->image, null, $this->get_quality() );
}
// Fall back to the default if webp isn't supported.
default:
header( 'Content-Type: image/jpeg' );
return imagejpeg( $this->image, null, $this->get_quality() );

View File

@@ -197,19 +197,30 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
}
try {
if ( 'image/jpeg' === $this->mime_type ) {
$this->image->setImageCompressionQuality( $quality );
$this->image->setImageCompression( imagick::COMPRESSION_JPEG );
} else {
$this->image->setImageCompressionQuality( $quality );
switch ( $this->mime_type ) {
case 'image/jpeg':
$this->image->setImageCompressionQuality( $quality );
$this->image->setImageCompression( imagick::COMPRESSION_JPEG );
break;
case 'image/webp':
if ( _wp_webp_is_lossy( $this->file ) ) {
$this->image->setImageCompressionQuality( $quality );
} else {
// Use WebP lossless settings.
$this->image->setImageCompressionQuality( 100 );
$this->image->setOption( 'webp:lossless', 'true' );
}
break;
default:
$this->image->setImageCompressionQuality( $quality );
}
} catch ( Exception $e ) {
return new WP_Error( 'image_quality_error', $e->getMessage() );
}
return true;
}
/**
* Sets or updates current image size.
*

View File

@@ -1141,7 +1141,7 @@ final class WP_Theme implements ArrayAccess {
return false;
}
foreach ( array( 'png', 'gif', 'jpg', 'jpeg' ) as $ext ) {
foreach ( array( 'png', 'gif', 'jpg', 'jpeg', 'webp' ) as $ext ) {
if ( file_exists( $this->get_stylesheet_directory() . "/screenshot.$ext" ) ) {
$this->cache_add( 'screenshot', 'screenshot.' . $ext );
if ( 'relative' === $uri ) {

View File

@@ -370,3 +370,11 @@ if ( ! function_exists( 'is_iterable' ) ) {
return ( is_array( $var ) || $var instanceof Traversable );
}
}
// WebP constants may not be defined, even in cases where the format is supported.
if ( ! defined( 'IMAGETYPE_WEBP' ) ) {
define( 'IMAGETYPE_WEBP', 18 );
}
if ( ! defined( 'IMG_WEBP' ) ) {
define( 'IMG_WEBP', IMAGETYPE_WEBP ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.imagetype_webpFound
}

View File

@@ -91,7 +91,7 @@ class WP_Customize_Media_Control extends WP_Customize_Control {
// Fake an attachment model - needs all fields used by template.
// Note that the default value must be a URL, NOT an attachment ID.
$ext = substr( $this->setting->default, -3 );
$type = in_array( $ext, array( 'jpg', 'png', 'gif', 'bmp' ), true ) ? 'image' : 'document';
$type = in_array( $ext, array( 'jpg', 'png', 'gif', 'bmp', 'webp' ), true ) ? 'image' : 'document';
$default_attachment = array(
'id' => 1,

View File

@@ -3340,6 +3340,8 @@ function gd_edit_image_support($mime_type) {
return (imagetypes() & IMG_PNG) != 0;
case 'image/gif':
return (imagetypes() & IMG_GIF) != 0;
case 'image/webp':
return (imagetypes() & IMG_WEBP) != 0; // phpcs:ignore PHPCompatibility.Constants.NewConstants.img_webpFound
}
} else {
switch( $mime_type ) {
@@ -3349,6 +3351,8 @@ function gd_edit_image_support($mime_type) {
return function_exists('imagecreatefrompng');
case 'image/gif':
return function_exists('imagecreatefromgif');
case 'image/webp':
return function_exists('imagecreatefromwebp');
}
}
return false;

View File

@@ -3318,7 +3318,7 @@ function translate_smiley( $matches ) {
$matches = array();
$ext = preg_match( '/\.([^.]+)$/', $img, $matches ) ? strtolower( $matches[1] ) : false;
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp' );
// Don't convert smilies that aren't images - they're probably emoji.
if ( ! in_array( $ext, $image_exts, true ) ) {

View File

@@ -2886,6 +2886,7 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
'image/gif' => 'gif',
'image/bmp' => 'bmp',
'image/tiff' => 'tif',
'image/webp' => 'webp',
)
);
@@ -3063,6 +3064,35 @@ function wp_get_image_mime( $file ) {
} else {
$mime = false;
}
if ( false !== $mime ) {
return $mime;
}
$handle = fopen( $file, 'rb' );
if ( false === $handle ) {
return false;
}
$magic = fread( $handle, 12 );
if ( false === $magic ) {
return false;
}
// Add WebP fallback detection when image library doesn't support WebP.
// Note: detection values come from LibWebP, see
// https://github.com/webmproject/libwebp/blob/master/imageio/image_dec.c#L30
$magic = bin2hex( $magic );
if (
// RIFF.
( 0 === strpos( $magic, '52494646' ) ) &&
// WEBP.
( 16 === strpos( $magic, '57454250' ) )
) {
$mime = 'image/webp';
}
fclose( $handle );
} catch ( Exception $e ) {
$mime = false;
}
@@ -3101,6 +3131,7 @@ function wp_get_mime_types() {
'png' => 'image/png',
'bmp' => 'image/bmp',
'tiff|tif' => 'image/tiff',
'webp' => 'image/webp',
'ico' => 'image/x-icon',
'heic' => 'image/heic',
// Video formats.
@@ -3222,7 +3253,7 @@ function wp_get_ext_types() {
return apply_filters(
'ext2type',
array(
'image' => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico', 'heic' ),
'image' => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico', 'heic', 'webp' ),
'audio' => array( 'aac', 'ac3', 'aif', 'aiff', 'flac', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
'video' => array( '3g2', '3gp', '3gpp', 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
'document' => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'xps', 'oxps', 'rtf', 'wp', 'wpd', 'psd', 'xcf' ),

View File

@@ -4980,6 +4980,7 @@ function wp_show_heic_upload_error( $plupload_settings ) {
* Allows PHP's getimagesize() to be debuggable when necessary.
*
* @since 5.7.0
* @since 5.8.0 Added support for WebP images.
*
* @param string $filename The file path.
* @param array $image_info Optional. Extended image information (passed by reference).
@@ -4994,9 +4995,9 @@ function wp_getimagesize( $filename, array &$image_info = null ) {
defined( 'WP_DEBUG' ) && WP_DEBUG
) {
if ( 2 === func_num_args() ) {
return getimagesize( $filename, $image_info );
return _wp_get_image_size( $filename, $image_info );
} else {
return getimagesize( $filename );
return _wp_get_image_size( $filename );
}
}
@@ -5011,9 +5012,133 @@ function wp_getimagesize( $filename, array &$image_info = null ) {
*/
if ( 2 === func_num_args() ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
return @getimagesize( $filename, $image_info );
return @_wp_get_image_size( $filename, $image_info );
} else {
// phpcs:ignore WordPress.PHP.NoSilencedErrors
return @getimagesize( $filename );
return @_wp_get_image_size( $filename );
}
}
/**
* Extracts meta information about a webp file: width, height and type.
*
* @since 5.8.0
*
* @param [type] $filename Path to a WebP file.
* @return array $webp_info {
* An array of WebP image information.
*
* @type array $size {
* @type int $width Image width.
* @type int $height Image height.
* @type bool $type The WebP type: one of 'lossy', 'lossless' or 'animated-alpha'.
* }
*/
function wp_get_webp_info( $filename ) {
$width = false;
$height = false;
$type = false;
if ( ! 'image/webp' === wp_get_image_mime( $filename ) ) {
return compact( 'width', 'height', 'type' );
}
try {
$handle = fopen( $filename, 'rb' );
if ( $handle ) {
$magic = fread( $handle, 40 );
fclose( $handle );
// Make sure we got enough bytes.
if ( strlen( $magic ) < 40 ) {
return compact( 'width', 'height', 'type' );
}
// The headers are a little different for each of the three formats.
// Header values based on WebP docs, see https://developers.google.com/speed/webp/docs/riff_container.
switch ( substr( $magic, 12, 4 ) ) {
// Lossy WebP.
case 'VP8 ':
$parts = unpack( 'v2', substr( $magic, 26, 4 ) );
$width = (int) ( $parts[1] & 0x3FFF );
$height = (int) ( $parts[2] & 0x3FFF );
$type = 'lossy';
break;
// Lossless WebP.
case 'VP8L':
$parts = unpack( 'C4', substr( $magic, 21, 4 ) );
$width = (int) ( $parts[1] | ( ( $parts[2] & 0x3F ) << 8 ) ) + 1;
$height = (int) ( ( ( $parts[2] & 0xC0 ) >> 6 ) | ( $parts[3] << 2 ) | ( ( $parts[4] & 0x03 ) << 10 ) ) + 1;
$type = 'lossless';
break;
// Animated/alpha WebP.
case 'VP8X':
// Pad 24-bit int.
$width = unpack( 'V', substr( $magic, 24, 3 ) . "\x00" );
$width = (int) ( $width[1] & 0xFFFFFF ) + 1;
// Pad 24-bit int.
$height = unpack( 'V', substr( $magic, 27, 3 ) . "\x00" );
$height = (int) ( $height[1] & 0xFFFFFF ) + 1;
$type = 'animated-alpha';
break;
}
}
} catch ( Exception $e ) {
}
return compact( 'width', 'height', 'type' );
}
/**
* Determines if a passed image is a lossy WebP image.
*
* @since 5.8.0
*
* @param string $filename The file path.
* @return bool Whether the file is a lossy WebP file.
*/
function _wp_webp_is_lossy( $filename ) {
$webp_info = wp_get_webp_info( $filename );
$type = $webp_info['type'];
return $type && 'lossy' === $type;
}
/**
* Gets the image size, with support for WebP images.
*
* @since 5.8.0
* @access private
*
* @param string $filename The file path.
* @param array $imageinfo Extended image information, passed by reference.
* @return array|false Array of image information or false on failure.
*/
function _wp_get_image_size( $filename, &$imageinfo = array() ) {
// Try getimagesize() first.
$info = getimagesize( $filename, $imageinfo );
if ( false !== $info ) {
return $info;
}
// For PHP versions that don't support WebP images, extract the image
// size info from the file headers.
if ( 'image/webp' === wp_get_image_mime( $filename ) ) {
$webp_info = wp_get_webp_info( $filename );
$width = $webp_info['width'];
$height = $webp_info['height'];
// Mimic the native return format.
if ( $width && $height ) {
return array(
$width,
$height,
IMAGETYPE_WEBP, // phpcs:ignore PHPCompatibility.Constants.NewConstants.imagetype_webpFound
sprintf(
'width="%d" height="%d"',
$width,
$height
),
'mime' => 'image/webp',
);
}
}
// The image could not be parsed.
return false;
}

View File

@@ -6539,7 +6539,7 @@ function wp_attachment_is( $type, $post = null ) {
switch ( $type ) {
case 'image':
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );
$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'webp' );
return in_array( $ext, $image_exts, true );
case 'audio':

View File

@@ -438,7 +438,7 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
);
}
$supported_types = array( 'image/jpeg', 'image/png', 'image/gif' );
$supported_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp' );
$mime_type = get_post_mime_type( $attachment_id );
if ( ! in_array( $mime_type, $supported_types, true ) ) {
return new WP_Error(

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -1225,6 +1225,29 @@ class Tests_Functions extends WP_UnitTestCase {
$this->assertSame( $expected, wp_get_image_mime( $file ) );
}
/**
* @ticket 35725
* @dataProvider data_wp_getimagesize
*/
public function test_wp_getimagesize( $file, $expected ) {
if ( ! is_callable( 'exif_imagetype' ) && ! function_exists( 'getimagesize' ) ) {
$this->markTestSkipped( 'The exif PHP extension is not loaded.' );
}
$result = wp_getimagesize( $file );
// The getimagesize() function varies in its response, so
// let's restrict comparison to expected keys only.
if ( is_array( $expected ) ) {
foreach ( $expected as $k => $v ) {
$this->assertEquals( true, isset( $result[ $k ] ) );
$this->assertEquals( $expected[ $k ], $result[ $k ] );
}
} else {
$this->assertEquals( $expected, $result );
}
}
/**
* @ticket 39550
* @dataProvider _wp_check_filetype_and_ext_data
@@ -1313,6 +1336,129 @@ class Tests_Functions extends WP_UnitTestCase {
DIR_TESTDATA . '/images/test-image-mime-jpg.png',
'image/jpeg',
),
// Animated WebP.
array(
DIR_TESTDATA . '/images/webp-animated.webp',
'image/webp',
),
// Lossless WebP.
array(
DIR_TESTDATA . '/images/webp-lossless.webp',
'image/webp',
),
// Lossy WebP.
array(
DIR_TESTDATA . '/images/webp-lossy.webp',
'image/webp',
),
// Transparent WebP.
array(
DIR_TESTDATA . '/images/webp-transparent.webp',
'image/webp',
),
// Not an image.
array(
DIR_TESTDATA . '/uploads/dashicons.woff',
false,
),
);
return $data;
}
/**
* Data profider for test_wp_getimagesize();
*/
public function data_wp_getimagesize() {
$data = array(
// Standard JPEG.
array(
DIR_TESTDATA . '/images/test-image.jpg',
array(
50,
50,
IMAGETYPE_JPEG,
'width="50" height="50"',
'mime' => 'image/jpeg',
),
),
// Standard GIF.
array(
DIR_TESTDATA . '/images/test-image.gif',
array(
50,
50,
IMAGETYPE_GIF,
'width="50" height="50"',
'mime' => 'image/gif',
),
),
// Standard PNG.
array(
DIR_TESTDATA . '/images/test-image.png',
array(
50,
50,
IMAGETYPE_PNG,
'width="50" height="50"',
'mime' => 'image/png',
),
),
// Image with wrong extension.
array(
DIR_TESTDATA . '/images/test-image-mime-jpg.png',
array(
50,
50,
IMAGETYPE_JPEG,
'width="50" height="50"',
'mime' => 'image/jpeg',
),
),
// Animated WebP.
array(
DIR_TESTDATA . '/images/webp-animated.webp',
array(
100,
100,
IMAGETYPE_WEBP,
'width="100" height="100"',
'mime' => 'image/webp',
),
),
// Lossless WebP.
array(
DIR_TESTDATA . '/images/webp-lossless.webp',
array(
1200,
675,
IMAGETYPE_WEBP,
'width="1200" height="675"',
'mime' => 'image/webp',
),
),
// Lossy WebP.
array(
DIR_TESTDATA . '/images/webp-lossy.webp',
array(
1200,
675,
IMAGETYPE_WEBP,
'width="1200" height="675"',
'mime' => 'image/webp',
),
),
// Transparent WebP.
array(
DIR_TESTDATA . '/images/webp-transparent.webp',
array(
1200,
675,
IMAGETYPE_WEBP,
'width="1200" height="675"',
'mime' => 'image/webp',
),
),
// Not an image.
array(
DIR_TESTDATA . '/uploads/dashicons.woff',

View File

@@ -195,4 +195,84 @@ class Tests_Image_Editor extends WP_Image_UnitTestCase {
$this->assertSame( '100x50', $editor->get_suffix() );
}
/**
* Test wp_get_webp_info.
*
* @ticket 35725
* @dataProvider _test_wp_get_webp_info
*
*/
public function test_wp_get_webp_info( $file, $expected ) {
$editor = wp_get_image_editor( $file );
if ( is_wp_error( $editor ) || ! $editor->supports_mime_type( 'image/webp' ) ) {
$this->markTestSkipped( sprintf( 'Skipping test: no WebP support in the editor engine %s on this system.', $this->editor_engine ) );
} else {
$file_data = wp_get_webp_info( $file );
$this->assertSame( $file_data, $expected );
}
}
/**
* Data provider for test_wp_get_webp_info();
*/
public function _test_wp_get_webp_info() {
return array(
// Standard JPEG.
array(
DIR_TESTDATA . '/images/test-image.jpg',
array(
'width' => false,
'height' => false,
'type' => false,
),
),
// Standard GIF.
array(
DIR_TESTDATA . '/images/test-image.gif',
array(
'width' => false,
'height' => false,
'type' => false,
),
),
// Animated WebP.
array(
DIR_TESTDATA . '/images/webp-animated.webp',
array(
'width' => 100,
'height' => 100,
'type' => 'animated-alpha',
),
),
// Lossless WebP.
array(
DIR_TESTDATA . '/images/webp-lossless.webp',
array(
'width' => 1200,
'height' => 675,
'type' => 'lossless',
),
),
// Lossy WebP.
array(
DIR_TESTDATA . '/images/webp-lossy.webp',
array(
'width' => 1200,
'height' => 675,
'type' => 'lossy',
),
),
// Transparent WebP.
array(
DIR_TESTDATA . '/images/webp-transparent.webp',
array(
'width' => 1200,
'height' => 675,
'type' => 'animated-alpha',
),
),
);
}
}

View File

@@ -59,6 +59,10 @@ class Tests_Image_Functions extends WP_UnitTestCase {
'test-image.psd',
'test-image-zip.tiff',
'test-image.jpg',
'webp-animated.webp',
'webp-lossless.webp',
'webp-lossy.webp',
'webp-transparent.webp',
);
// IMAGETYPE_ICO is only defined in PHP 5.3+.
@@ -92,6 +96,21 @@ class Tests_Image_Functions extends WP_UnitTestCase {
'test-image.jpg',
);
// Add WebP images if the image editor supports them.
$file = DIR_TESTDATA . '/images/test-image.webp';
$editor = wp_get_image_editor( $file );
if ( ( ! is_wp_error( $editor ) ) && $editor->supports_mime_type( 'image/webp' ) ) {
$files = array_merge(
$files,
array(
'webp-animated.webp',
'webp-lossless.webp',
'webp-lossy.webp',
'webp-transparent.webp',
)
);
}
// IMAGETYPE_ICO is only defined in PHP 5.3+.
if ( defined( 'IMAGETYPE_ICO' ) ) {
$files[] = 'test-image.ico';
@@ -174,6 +193,11 @@ class Tests_Image_Functions extends WP_UnitTestCase {
'image/png',
);
// Include WebP in tests when platform supports it.
if ( function_exists( 'imagewebp' ) ) {
array_push( $mime_types, 'image/webp' );
}
// Test each image editor engine.
foreach ( $classes as $class ) {
$img = new $class( DIR_TESTDATA . '/images/canola.jpg' );
@@ -270,7 +294,8 @@ class Tests_Image_Functions extends WP_UnitTestCase {
'jpe' => 'image/jpeg',
'gif' => 'image/gif',
'png' => 'image/png',
'unk' => 'image/jpeg', // Default, unknown.
'webp' => 'image/webp',
'unk' => 'image/jpeg', // Default, unknown.
);
// Test each image editor engine.

View File

@@ -64,6 +64,24 @@ abstract class WP_Tests_Image_Resize_UnitTestCase extends WP_Image_UnitTestCase
unlink( $image );
}
function test_resize_webp() {
$file = DIR_TESTDATA . '/images/test-image.webp';
$editor = wp_get_image_editor( $file );
// Check if the editor supports the webp mime type.
if ( is_wp_error( $editor ) || ! $editor->supports_mime_type( 'image/webp' ) ) {
$this->markTestSkipped( sprintf( 'Skipping test: no WebP support in the editor engine %s on this system.', $this->editor_engine ) );
} else {
$image = $this->resize_helper( $file, 25, 25 );
$this->assertSame( 'test-image-25x25.webp', wp_basename( $image ) );
list($w, $h, $type) = wp_getimagesize( $image );
$this->assertSame( 25, $w );
$this->assertSame( 25, $h );
$this->assertSame( IMAGETYPE_WEBP, $type );
unlink( $image );
}
}
function test_resize_larger() {
// image_resize() should refuse to make an image larger.
$image = $this->resize_helper( DIR_TESTDATA . '/images/test-image.jpg', 100, 100 );