Skip to content

Commit

Permalink
Media: improve filter to enable setting output quality by image size.
Browse files Browse the repository at this point in the history
Add a new $size parameter to the  wp_editor_set_quality filter. $size is an array with 'width' and 'height' keys. Developers can use this information to set image quality based on the image size.

Props adamsilverstein, joemcgill, Mte90, codekraft, birgire, azaozz, sppramodh.
Fixes #54648.




git-svn-id: https://develop.svn.wordpress.org/trunk@59473 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
adamsilverstein committed Nov 29, 2024
1 parent dfcdeaf commit 0671dfd
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 10 deletions.
18 changes: 14 additions & 4 deletions src/wp-includes/class-wp-image-editor-gd.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ protected function _resize( $max_w, $max_h, $crop = false ) {

list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;

$this->set_quality(
null,
array(
'width' => $dst_w,
'height' => $dst_h,
)
);

$resized = wp_imagecreatetruecolor( $dst_w, $dst_h );
imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );

Expand Down Expand Up @@ -568,12 +576,14 @@ 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
* @since 6.8.0 The `$dims` parameter was added.
*
* @param int $quality Compression Quality. Range: [1,100]
* @param int $quality Compression Quality. Range: [1,100]
* @param array $dims Optional. Image dimensions array with 'width' and 'height' keys.
* @return true|WP_Error True if set successfully; WP_Error on failure.
*/
public function set_quality( $quality = null ) {
$quality_result = parent::set_quality( $quality );
public function set_quality( $quality = null, $dims = array() ) {
$quality_result = parent::set_quality( $quality, $dims );
if ( is_wp_error( $quality_result ) ) {
return $quality_result;
} else {
Expand All @@ -586,7 +596,7 @@ public function set_quality( $quality = null ) {
$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 );
parent::set_quality( $quality, $dims );
}
}
} catch ( Exception $e ) {
Expand Down
16 changes: 13 additions & 3 deletions src/wp-includes/class-wp-image-editor-imagick.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,14 @@ public function load() {
* Sets Image Compression quality on a 1-100% scale.
*
* @since 3.5.0
* @since 6.8.0 The `$dims` parameter was added.
*
* @param int $quality Compression Quality. Range: [1,100]
* @param int $quality Compression Quality. Range: [1,100]
* @param array $dims Optional. Image dimensions array with 'width' and 'height' keys.
* @return true|WP_Error True if set successfully; WP_Error on failure.
*/
public function set_quality( $quality = null ) {
$quality_result = parent::set_quality( $quality );
public function set_quality( $quality = null, $dims = array() ) {
$quality_result = parent::set_quality( $quality, $dims );
if ( is_wp_error( $quality_result ) ) {
return $quality_result;
} else {
Expand Down Expand Up @@ -367,6 +369,14 @@ public function resize( $max_w, $max_h, $crop = false ) {
return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
}

$this->set_quality(
null,
array(
'width' => $dst_w,
'height' => $dst_h,
)
);

// Execute the resize.
$thumb_result = $this->thumbnail_image( $dst_w, $dst_h );
if ( is_wp_error( $thumb_result ) ) {
Expand Down
16 changes: 13 additions & 3 deletions src/wp-includes/class-wp-image-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,14 @@ public function get_quality() {
* Sets Image Compression quality on a 1-100% scale.
*
* @since 3.5.0
* @since 6.8.0 The `$dims` parameter was added.
*
* @param int $quality Compression Quality. Range: [1,100]
* @param int $quality Compression Quality. Range: [1,100]
* @param array $dims Optional. Image dimensions array with 'width' and 'height' keys.
* @return true|WP_Error True if set successfully; WP_Error on failure.
*/
public function set_quality( $quality = null ) {
public function set_quality( $quality = null, $dims = array() ) {
// Use the output mime type if present. If not, fall back to the input/initial mime type.
$mime_type = ! empty( $this->output_mime_type ) ? $this->output_mime_type : $this->mime_type;
// Get the default quality setting for the mime type.
Expand All @@ -260,11 +263,18 @@ public function set_quality( $quality = null ) {
* The WP_Image_Editor::set_quality() method has priority over the filter.
*
* @since 3.5.0
* @since 6.8.0 Added the size parameter.
*
* @param int $quality Quality level between 1 (low) and 100 (high).
* @param string $mime_type Image mime type.
* @param array $size {
* Dimensions of the image.
*
* @type int $width The image width.
* @type int $height The image height.
* }
*/
$quality = apply_filters( 'wp_editor_set_quality', $default_quality, $mime_type );
$quality = apply_filters( 'wp_editor_set_quality', $default_quality, $mime_type, $dims ? $dims : $this->size );

if ( 'image/jpeg' === $mime_type ) {
/**
Expand Down
45 changes: 45 additions & 0 deletions tests/phpunit/tests/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -5433,6 +5433,51 @@ public function test_quality_with_avif_conversion_file_sizes() {
}
}

/**
* Test that the `wp_editor_set_quality` filter includes the dimensions in the `$dims` parameter.
*
* @ticket 54648
*/
public function test_wp_editor_set_quality_includes_dimensions() {
// Before loading an image, set up the callback filter with the assertions.
add_filter( 'wp_editor_set_quality', array( $this, 'assert_dimensions_in_wp_editor_set_quality' ), 10, 3 );

$temp_dir = get_temp_dir();
$file = $temp_dir . '/33772.jpg';
copy( DIR_TESTDATA . '/images/33772.jpg', $file );

$editor = wp_get_image_editor( $file );

$attachment_id = self::factory()->attachment->create_object(
array(
'post_mime_type' => 'image/jpeg',
'file' => $file,
)
);

// Generate all sizes.
wp_generate_attachment_metadata( $attachment_id, $file );

// Clean up the filter.
remove_filter( 'wp_editor_set_quality', array( $this, 'assert_dimensions_in_wp_editor_set_quality' ), 10, 3 );
}

/**
* Helper callback to assert that the dimensions are included in the `$dims` parameter.
*
* @param int $quality The quality level.
* @param array $dims The dimensions array.
*/
public function assert_dimensions_in_wp_editor_set_quality( $quality, $mime_type, $dims ) {
// Assert that the array has non empty width and height values.
$this->assertArrayHasKey( 'width', $dims );
$this->assertArrayHasKey( 'height', $dims );
$this->assertGreaterThan( 0, $dims['width'] );
$this->assertGreaterThan( 0, $dims['height'] );

return $quality;
}

/**
* Test that an image size isn't generated if it matches the original image size.
*
Expand Down

0 comments on commit 0671dfd

Please sign in to comment.