Skip to content

Commit

Permalink
Media: improve support for lossless WebP.
Browse files Browse the repository at this point in the history
When uploading lossless WebP images, WordPress now correctly outputs lossless WebP with both the Imagick and GD image editors.

Props: adamsilverstein, martinkrcho.
Fixes #60291.



git-svn-id: https://develop.svn.wordpress.org/trunk@59145 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
adamsilverstein committed Sep 30, 2024
1 parent 9b6c034 commit 9ef1ff1
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/wp-includes/class-wp-image-editor-gd.php
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,38 @@ protected function _save( $image, $filename = null, $mime_type = null ) {
);
}

/**
* Sets Image Compression quality on a 1-100% scale. Handles WebP lossless images.
*
* @since 6.7.0
*
* @param int $quality Compression Quality. Range: [1,100]
* @return true|WP_Error True if set successfully; WP_Error on failure.
*/
public function set_quality( $quality = null ) {
$quality_result = parent::set_quality( $quality );
if ( is_wp_error( $quality_result ) ) {
return $quality_result;
} else {
$quality = $this->get_quality();
}

// Handle setting the quality for WebP lossless images, see https://php.watch/versions/8.1/gd-webp-lossless.
try {
if ( 'image/webp' === $this->mime_type && defined( 'IMG_WEBP_LOSSLESS' ) ) {
$webp_info = wp_get_webp_info( $this->file );
if ( ! empty( $webp_info['type'] ) && 'lossless' === $webp_info['type'] ) {
$quality = IMG_WEBP_LOSSLESS;
parent::set_quality( $quality );
}
}
} catch ( Exception $e ) {
return new WP_Error( 'image_quality_error', $e->getMessage() );
}
$this->quality = $quality;
return true;
}

/**
* Returns stream of current image.
*
Expand Down
1 change: 1 addition & 0 deletions src/wp-includes/class-wp-image-editor-imagick.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ public function set_quality( $quality = null ) {
// Use WebP lossless settings.
$this->image->setImageCompressionQuality( 100 );
$this->image->setOption( 'webp:lossless', 'true' );
parent::set_quality( 100 );
} else {
$this->image->setImageCompressionQuality( $quality );
}
Expand Down
28 changes: 28 additions & 0 deletions tests/phpunit/tests/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -6103,6 +6103,34 @@ static function ( $loading_attrs ) {
);
}


/**
* Test WebP lossless quality is handled correctly.
*
* @ticket 60291
*/
public function test_set_quality_webp_lossless() {
// Get a new editor to test that lossless WebP images are handled correctly.
$editor = wp_get_image_editor( DIR_TESTDATA . '/images/webp-lossless.webp' );

// If no editor is available, skip the test.
if ( is_wp_error( $editor ) ) {
$this->markTestSkipped( 'No editor available for lossless WebP images.' );
}

// Only test on GD when WebP lossless is supported.
if ( 'WP_Image_Editor_GD' === get_class( $editor ) && ! defined( 'IMG_WEBP_LOSSLESS' ) ) {
$this->markTestSkipped( 'No GD support available for lossless WebP images.' );
}

// Verify lossless quality is set correctly: IMG_WEBP_LOSSLESS for GD and 100 for Imagick.
if ( 'WP_Image_Editor_GD' === get_class( $editor ) ) {
$this->assertSame( IMG_WEBP_LOSSLESS, $editor->get_quality() );
} else {
$this->assertSame( 100, $editor->get_quality() );
}
}

/**
* Test generated markup for an image with lazy loading gets auto-sizes.
*
Expand Down

0 comments on commit 9ef1ff1

Please sign in to comment.