Skip to content

Commit 108369e

Browse files
Media: improve support for lossless WebP.
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/branches/6.5@59136 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 366c8e5 commit 108369e

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

src/wp-includes/class-wp-image-editor-gd.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,38 @@ protected function _save( $image, $filename = null, $mime_type = null ) {
567567
);
568568
}
569569

570+
/**
571+
* Sets Image Compression quality on a 1-100% scale. Handles WebP lossless images.
572+
*
573+
* @since 6.7.0
574+
*
575+
* @param int $quality Compression Quality. Range: [1,100]
576+
* @return true|WP_Error True if set successfully; WP_Error on failure.
577+
*/
578+
public function set_quality( $quality = null ) {
579+
$quality_result = parent::set_quality( $quality );
580+
if ( is_wp_error( $quality_result ) ) {
581+
return $quality_result;
582+
} else {
583+
$quality = $this->get_quality();
584+
}
585+
586+
// Handle setting the quality for WebP lossless images, see https://php.watch/versions/8.1/gd-webp-lossless.
587+
try {
588+
if ( 'image/webp' === $this->mime_type && defined( 'IMG_WEBP_LOSSLESS' ) ) {
589+
$webp_info = wp_get_webp_info( $this->file );
590+
if ( ! empty( $webp_info['type'] ) && 'lossless' === $webp_info['type'] ) {
591+
$quality = IMG_WEBP_LOSSLESS;
592+
parent::set_quality( $quality );
593+
}
594+
}
595+
} catch ( Exception $e ) {
596+
return new WP_Error( 'image_quality_error', $e->getMessage() );
597+
}
598+
$this->quality = $quality;
599+
return true;
600+
}
601+
570602
/**
571603
* Returns stream of current image.
572604
*

src/wp-includes/class-wp-image-editor-imagick.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ public function set_quality( $quality = null ) {
215215
// Use WebP lossless settings.
216216
$this->image->setImageCompressionQuality( 100 );
217217
$this->image->setOption( 'webp:lossless', 'true' );
218+
parent::set_quality( 100 );
218219
} else {
219220
$this->image->setImageCompressionQuality( $quality );
220221
}

tests/phpunit/tests/media.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6081,6 +6081,34 @@ private function get_width_height_for_high_priority() {
60816081
);
60826082
}
60836083

6084+
6085+
/**
6086+
* Test WebP lossless quality is handled correctly.
6087+
*
6088+
* @ticket 60291
6089+
*/
6090+
public function test_set_quality_webp_lossless() {
6091+
// Get a new editor to test that lossless WebP images are handled correctly.
6092+
$editor = wp_get_image_editor( DIR_TESTDATA . '/images/webp-lossless.webp' );
6093+
6094+
// If no editor is available, skip the test.
6095+
if ( is_wp_error( $editor ) ) {
6096+
$this->markTestSkipped( 'No editor available for lossless WebP images.' );
6097+
}
6098+
6099+
// Only test on GD when WebP lossless is supported.
6100+
if ( 'WP_Image_Editor_GD' === get_class( $editor ) && ! defined( 'IMG_WEBP_LOSSLESS' ) ) {
6101+
$this->markTestSkipped( 'No GD support available for lossless WebP images.' );
6102+
}
6103+
6104+
// Verify lossless quality is set correctly: IMG_WEBP_LOSSLESS for GD and 100 for Imagick.
6105+
if ( 'WP_Image_Editor_GD' === get_class( $editor ) ) {
6106+
$this->assertSame( IMG_WEBP_LOSSLESS, $editor->get_quality() );
6107+
} else {
6108+
$this->assertSame( 100, $editor->get_quality() );
6109+
}
6110+
}
6111+
60846112
/**
60856113
* Returns an array with dimension attribute values ineligible for a high priority image.
60866114
*

0 commit comments

Comments
 (0)