Media: apply the wp_editor_set_quality filter not only when loading an image in the editor but also when saving an converted image, after the mime-type of the output image has changed.

Props mikeschroder, desrosj, azaozz.
Fixes #53667.

git-svn-id: https://develop.svn.wordpress.org/trunk@51704 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Ozz
2021-08-31 18:57:09 +00:00
parent 9002ba2e04
commit 1bbc5a4737
3 changed files with 137 additions and 5 deletions
+49 -5
View File
@@ -15,9 +15,12 @@ abstract class WP_Image_Editor {
protected $file = null;
protected $size = null;
protected $mime_type = null;
protected $output_mime_type = null;
protected $default_mime_type = 'image/jpeg';
protected $quality = false;
protected $default_quality = 82;
// Deprecated since 5.8.1. See get_default_quality() below.
protected $default_quality = 82;
/**
* Each instance handles a single file.
@@ -224,6 +227,11 @@ abstract class WP_Image_Editor {
* @return true|WP_Error True if set successfully; WP_Error on failure.
*/
public function set_quality( $quality = null ) {
// 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.
$default_quality = $this->get_default_quality( $mime_type );
if ( null === $quality ) {
/**
* Filters the default image compression quality setting.
@@ -238,9 +246,9 @@ abstract class WP_Image_Editor {
* @param int $quality Quality level between 1 (low) and 100 (high).
* @param string $mime_type Image mime type.
*/
$quality = apply_filters( 'wp_editor_set_quality', $this->default_quality, $this->mime_type );
$quality = apply_filters( 'wp_editor_set_quality', $default_quality, $mime_type );
if ( 'image/jpeg' === $this->mime_type ) {
if ( 'image/jpeg' === $mime_type ) {
/**
* Filters the JPEG compression quality for backward-compatibility.
*
@@ -261,7 +269,7 @@ abstract class WP_Image_Editor {
}
if ( $quality < 0 || $quality > 100 ) {
$quality = $this->default_quality;
$quality = $default_quality;
}
}
@@ -278,6 +286,27 @@ abstract class WP_Image_Editor {
}
}
/**
* Returns the default compression quality setting for the mime type.
*
* @since 5.8.1
*
* @param string $mime_type
* @return int The default quality setting for the mime type.
*/
protected function get_default_quality( $mime_type ) {
switch ( $mime_type ) {
case 'image/webp':
$quality = 86;
break;
case 'image/jpeg':
default:
$quality = $this->default_quality;
}
return $quality;
}
/**
* Returns preferred mime-type and extension based on provided
* file's extension and mime, or current file's extension and mime.
@@ -374,13 +403,28 @@ abstract class WP_Image_Editor {
$new_ext = $this->get_extension( $mime_type );
}
if ( $filename ) {
// Ensure both $filename and $new_ext are not empty.
// $this->get_extension() returns false on error which would effectively remove the extension
// from $filename. That shouldn't happen, files without extensions are not supported.
if ( $filename && $new_ext ) {
$dir = pathinfo( $filename, PATHINFO_DIRNAME );
$ext = pathinfo( $filename, PATHINFO_EXTENSION );
$filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}";
}
if ( $mime_type && ( $mime_type !== $this->mime_type ) ) {
// The image will be converted when saving. Set the quality for the new mime-type if not already set.
if ( $mime_type !== $this->output_mime_type ) {
$this->output_mime_type = $mime_type;
$this->set_quality();
}
} elseif ( ! empty( $this->output_mime_type ) ) {
// Reset output_mime_type and quality.
$this->output_mime_type = null;
$this->set_quality();
}
return array( $filename, $new_ext, $mime_type );
}
@@ -56,6 +56,8 @@ if ( class_exists( 'WP_Image_Editor' ) ) :
}
}
public function save( $destfilename = null, $mime_type = null ) {
// Set new mime-type and quality if converting the image.
$this->get_output_format( $destfilename, $mime_type );
return self::$save_return;
}
public function stream( $mime_type = null ) {
+86
View File
@@ -110,6 +110,92 @@ class Tests_Image_Editor extends WP_Image_UnitTestCase {
remove_filter( 'wp_editor_set_quality', $func_100_percent );
}
/**
* Test test_quality when converting image
*
* @ticket 6821
*/
public function test_set_quality_with_image_conversion() {
$editor = wp_get_image_editor( DIR_TESTDATA . '/images/test-image.png' );
$editor->set_mime_type( 'image/png' ); // Ensure mime-specific filters act properly.
// Set conversions for uploaded images.
add_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) );
// Quality setting for the source image. For PNG the fallback default of 82 is used.
$this->assertSame( 82, $editor->get_quality(), 'Default quality setting is 82.' );
// Quality should change to the output format's value.
// A PNG image will be converted to WEBP whose quialty should be 86.
$editor->save();
$this->assertSame( 86, $editor->get_quality(), 'Output image format is WEBP. Quality setting for it should be 86.' );
// Removing PNG to WEBP conversion on save. Quality setting should reset to the default.
remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) );
$editor->save();
$this->assertSame( 82, $editor->get_quality(), 'After removing image conversion quality setting should reset to the default of 82.' );
unset( $editor );
// Set conversions for uploaded images.
add_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) );
// Change the quality values.
add_filter( 'wp_editor_set_quality', array( $this, 'image_editor_change_quality' ), 10, 2 );
// Get a new editor to clear quality state.
$editor = wp_get_image_editor( DIR_TESTDATA . '/images/test-image.jpg' );
$editor->set_mime_type( 'image/jpeg' );
$this->assertSame( 56, $editor->get_quality(), 'Filtered default quality for JPEG is 56.' );
// Quality should change to the output format's value as filtered above.
// A JPEG image will be converted to WEBP whose quialty should be 42.
$editor->save();
$this->assertSame( 42, $editor->get_quality(), 'Image conversion from JPEG to WEBP. Filtered WEBP quality shoild be 42.' );
// After removing the conversion the quality setting should reset to the filtered value for the original image type, JPEG.
remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) );
$editor->save();
$this->assertSame(
56,
$editor->get_quality(),
'After removing image conversion the quality setting should reset to the filtered value for JPEG, 56.'
);
remove_filter( 'wp_editor_set_quality', array( $this, 'image_editor_change_quality' ) );
}
/**
* Changes the output format when editing images. PNG and JPEG files
* will be converted to WEBP (if the image editor in PHP supports it).
*
* @param array $formats
*
* @return array
*/
public function image_editor_output_formats( $formats ) {
$formats['image/png'] = 'image/webp';
$formats['image/jpeg'] = 'image/webp';
return $formats;
}
/**
* Changes the quality according to the mime-type.
*
* @param int $quality Default quality.
* @param string $mime_type Image mime-type.
* @return int The changed quality.
*/
public function image_editor_change_quality( $quality, $mime_type ) {
if ( 'image/jpeg' === $mime_type ) {
return 56;
} elseif ( 'image/webp' === $mime_type ) {
return 42;
} else {
return 30;
}
}
/**
* Test generate_filename
*