From 8a3c33c86122bb917f9bd446417f50137dd620ca Mon Sep 17 00:00:00 2001 From: Andrew Nacin Date: Wed, 4 Dec 2013 22:48:45 +0000 Subject: [PATCH] Improvements to image quality handling in the image editor classes. props markoheijnen, DH-Shredder. fixes #25721. git-svn-id: https://develop.svn.wordpress.org/trunk@26645 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-image-editor-gd.php | 31 +++++++++++----- .../class-wp-image-editor-imagick.php | 26 ++++++++------ src/wp-includes/class-wp-image-editor.php | 36 ++++++++++++++++--- 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/wp-includes/class-wp-image-editor-gd.php b/src/wp-includes/class-wp-image-editor-gd.php index a8235c241d..3735cd8076 100644 --- a/src/wp-includes/class-wp-image-editor-gd.php +++ b/src/wp-includes/class-wp-image-editor-gd.php @@ -77,7 +77,7 @@ class WP_Image_Editor_GD extends WP_Image_Editor { * @since 3.5.0 * @access protected * - * @return boolean|\WP_Error + * @return boolean|WP_Error True if loaded successfully; WP_Error on failure. */ public function load() { if ( $this->image ) @@ -86,8 +86,16 @@ class WP_Image_Editor_GD extends WP_Image_Editor { if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); + /** + * Filter the memory limit allocated for image manipulation. + * + * @since 3.5.0 + * + * @param int Maximum memory limit to allocate (default is WP_MAX_MEMORY_LIMIT) + */ // Set artificially high because GD uses uncompressed images in memory @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); if ( ! is_resource( $this->image ) ) @@ -105,7 +113,7 @@ class WP_Image_Editor_GD extends WP_Image_Editor { $this->update_size( $size[0], $size[1] ); $this->mime_type = $size['mime']; - return true; + return $this->set_quality( $this->quality ); } /** @@ -361,7 +369,7 @@ class WP_Image_Editor_GD extends WP_Image_Editor { return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); } elseif ( 'image/jpeg' == $mime_type ) { - if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) ) + if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, $this->quality ) ) ) return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); } else { @@ -373,12 +381,19 @@ class WP_Image_Editor_GD extends WP_Image_Editor { $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits @ chmod( $filename, $perms ); + /** + * Filter the name of the saved image file. + * + * @since 2.6.0 + * + * @param string $filename Name of the file. + */ return array( - 'path' => $filename, - 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), - 'width' => $this->size['width'], - 'height' => $this->size['height'], - 'mime-type'=> $mime_type, + 'path' => $filename, + 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), + 'width' => $this->size['width'], + 'height' => $this->size['height'], + 'mime-type' => $mime_type, ); } diff --git a/src/wp-includes/class-wp-image-editor-imagick.php b/src/wp-includes/class-wp-image-editor-imagick.php index 2e1bebc994..d48213fa27 100644 --- a/src/wp-includes/class-wp-image-editor-imagick.php +++ b/src/wp-includes/class-wp-image-editor-imagick.php @@ -119,6 +119,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); + /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ // Even though Imagick uses less PHP memory than GD, set higher limit for users that have low PHP.ini limits @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); @@ -142,7 +143,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { if ( is_wp_error( $updated_size ) ) return $updated_size; - return $this->set_quality(); + return $this->set_quality( $this->quality ); } /** @@ -152,15 +153,19 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { * @access public * * @param int $quality Compression Quality. Range: [1,100] - * @return boolean|WP_Error + * @return boolean|WP_Error True if set successfully; WP_Error on failure. */ public function set_quality( $quality = null ) { - if ( !$quality ) + $quality_result = parent::set_quality( $quality ); + if ( is_wp_error( $quality_result ) ) { + return $quality_result; + } else { $quality = $this->quality; + } try { - if( 'image/jpeg' == $this->mime_type ) { - $this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) ); + if ( 'image/jpeg' == $this->mime_type ) { + $this->image->setImageCompressionQuality( $quality ); $this->image->setImageCompression( imagick::COMPRESSION_JPEG ); } else { @@ -171,7 +176,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { return new WP_Error( 'image_quality_error', $e->getMessage() ); } - return parent::set_quality( $quality ); + return true; } /** @@ -447,11 +452,12 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits @ chmod( $filename, $perms ); + /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */ return array( - 'path' => $filename, - 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), - 'width' => $this->size['width'], - 'height' => $this->size['height'], + 'path' => $filename, + 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), + 'width' => $this->size['width'], + 'height' => $this->size['height'], 'mime-type' => $mime_type, ); } diff --git a/src/wp-includes/class-wp-image-editor.php b/src/wp-includes/class-wp-image-editor.php index 81909f89be..3570ca96fa 100644 --- a/src/wp-includes/class-wp-image-editor.php +++ b/src/wp-includes/class-wp-image-editor.php @@ -205,19 +205,45 @@ abstract class WP_Image_Editor { * @access public * * @param int $quality Compression Quality. Range: [1,100] - * @return boolean + * @return boolean|WP_Error True if set successfully; WP_Error on failure. */ - public function set_quality( $quality ) { + public function set_quality( $quality = null ) { + if ( $quality == null ) { + $quality = $this->quality; + } + /** * Filter the default quality setting. * * @since 3.5.0 * - * @param int $quality Quality level between 0 (low) and 100 (high). + * @param int $quality Quality level between 1 (low) and 100 (high). */ - $this->quality = apply_filters( 'wp_editor_set_quality', $quality ); + $quality = apply_filters( 'wp_editor_set_quality', $quality, $this->mime_type ); - return ( (bool) $this->quality ); + /** + * Filter the JPEG quality for backwards compatibilty. + * + * @since 2.5.0 + * + * @param int $quality Quality level between 0 (low) and 100 (high) of the JPEG. + * @param string The context of the filter. + */ + if ( 'image/jpeg' == $this->mime_type ) { + $quality = apply_filters( 'jpeg_quality', $quality, 'image_resize' ); + + // Allow 0, but squash to 1 due to identical images in GD, and for backwards compatibility. + if ( $quality == 0 ) { + $quality = 1; + } + } + + if ( ( $quality >= 1 ) && ( $quality <= 100 ) ){ + $this->quality = $quality; + return true; + } else { + return new WP_Error( 'invalid_image_quality', __('Attempted to set image quality outside of the range [1,100].') ); + } } /**