WordPress.org

Make WordPress Core

Ticket #33642: 33642.2.patch

File 33642.2.patch, 7.9 KB (added by joemcgill, 4 years ago)

add custom thumbnailImage() method

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

    diff --git src/wp-includes/class-wp-image-editor-imagick.php src/wp-includes/class-wp-image-editor-imagick.php
    index a14fa40..b026327 100644
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    254254                         * @TODO: Thumbnail is more efficient, given a newer version of Imagemagick.
    255255                         * $this->image->thumbnailImage( $dst_w, $dst_h );
    256256                         */
    257                         $this->image->scaleImage( $dst_w, $dst_h );
     257                        $this->image->setOption( 'filter:support', '2.0' );
     258                        $this->thumbnailImage( $max_w, $max_h, false, false, Imagick::FILTER_TRIANGLE );
     259
     260                        // Set quality filters.
     261                        $this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 );
     262                        $this->image->setOption( 'jpeg:fancy-upsampling', 'off' );
     263
     264                        // Strip profiles.
     265                        $this->strip_profiles();
    258266                }
    259267                catch ( Exception $e ) {
    260268                        return new WP_Error( 'image_resize_error', $e->getMessage() );
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    530538
    531539                return true;
    532540        }
     541
     542        /**
     543         * Changes the size of an image to the given dimensions.
     544         *
     545         * `thumbnailImage` changes the size of an image to the given dimensions and
     546         * removes any associated profiles. The goal is to produce small low cost
     547         * thumbnail images suited for display on the Web.
     548         *
     549         * With the original Imagick thumbnailImage implementation, there is no way to choose a
     550         * resampling filter. This class recreates Imagick’s C implementation and adds this
     551         * additional feature.
     552         *
     553         * @access      public
     554         *
     555         * @param integer $columns The number of columns in the output image. 0 = maintain aspect ratio based on $rows.
     556         * @param integer $rows    The number of rows in the output image. 0 = maintain aspect ratio based on $columns.
     557         * @param bool    $bestfit Treat $columns and $rows as a bounding box in which to fit the image.
     558         * @param bool    $fill    Fill in the bounding box with the background colour.
     559         * @param integer $filter  The resampling filter to use. Refer to the list of filter constants at <http://php.net/manual/en/imagick.constants.php>.
     560         *
     561         * @return bool Indicates whether the operation was performed successfully.
     562         */
     563        public function thumbnailImage( $columns, $rows, $bestfit = false, $fill = false, $filter = Imagick::FILTER_TRIANGLE ) {
     564                /*
     565                 * Sample factor; defined in original ImageMagick thumbnailImage function
     566                 * the scale to which the image should be resized using the 'sample' function.
     567                 */
     568                $SampleFactor = 5;
     569                // Filter whitelist.
     570                $filters = array(
     571                        Imagick::FILTER_POINT,
     572                        Imagick::FILTER_BOX,
     573                        Imagick::FILTER_TRIANGLE,
     574                        Imagick::FILTER_HERMITE,
     575                        Imagick::FILTER_HANNING,
     576                        Imagick::FILTER_HAMMING,
     577                        Imagick::FILTER_BLACKMAN,
     578                        Imagick::FILTER_GAUSSIAN,
     579                        Imagick::FILTER_QUADRATIC,
     580                        Imagick::FILTER_CUBIC,
     581                        Imagick::FILTER_CATROM,
     582                        Imagick::FILTER_MITCHELL,
     583                        Imagick::FILTER_LANCZOS,
     584                        Imagick::FILTER_BESSEL,
     585                        Imagick::FILTER_SINC
     586                );
     587                // Parse parameters given to function.
     588                $columns = (double) $columns;
     589                $rows = (double) $rows;
     590                $bestfit = (bool) $bestfit;
     591                $fill = (bool) $fill;
     592                // We can’t resize to (0,0).
     593                if ( $rows < 1 && $columns < 1 ) {
     594                        return false;
     595                }
     596                // Set a default filter if an acceptable one wasn’t passed.
     597                if ( ! in_array( $filter, $filters ) ) {
     598                        $filter = Imagick::FILTER_TRIANGLE;
     599                }
     600                // Figure out the output width and height.
     601                $width = (double) $this->image->getImageWidth();
     602                $height = (double) $this->image->getImageHeight();
     603                $new_width = $columns;
     604                $new_height = $rows;
     605                $x_factor = $columns / $width;
     606                $y_factor = $rows / $height;
     607                if ( $rows < 1 ) {
     608                        $new_height = round( $x_factor * $height );
     609                } elseif ( $columns < 1 ) {
     610                        $new_width = round( $y_factor * $width );
     611                }
     612                /*
     613                 * If bestfit is true, the new_width/new_height of the image will be different than
     614                 * the columns/rows parameters; those will define a bounding box in which the image will be fit.
     615                 */
     616                if ( $bestfit && $x_factor > $y_factor ) {
     617                        $x_factor = $y_factor;
     618                        $new_width = round( $y_factor * $width );
     619                } elseif ( $bestfit && $y_factor > $x_factor ) {
     620                        $y_factor = $x_factor;
     621                        $new_height = round( $x_factor * $height );
     622                }
     623                if ( $new_width < 1 ) {
     624                        $new_width = 1;
     625                }
     626                if ( $new_height < 1 ) {
     627                        $new_height = 1;
     628                }
     629                /*
     630                 * If we’re resizing the image to more than about 1/3 it’s original size
     631                 * then just use the resize function.
     632                 */
     633                if ( ( $x_factor * $y_factor ) > 0.1 ) {
     634                        $this->image->resizeImage( $new_width, $new_height, $filter, 1 );
     635                // if we’d be using sample to scale to smaller than 128x128, just use resize
     636                } elseif ( ( ( $SampleFactor * $new_width ) < 128) || ( ( $SampleFactor * $new_height ) < 128 ) ) {
     637                                $this->image->resizeImage( $new_width, $new_height, $filter, 1 );
     638                // otherwise, use sample first, then resize
     639                } else {
     640                        $this->image->sampleImage( $SampleFactor * $new_width, $SampleFactor * $new_height );
     641                        $this->image->resizeImage( $new_width, $new_height, $filter, 1 );
     642                }
     643                // if the alpha channel is not defined, make it opaque
     644                if ( $this->image->getImageAlphaChannel() == Imagick::ALPHACHANNEL_UNDEFINED ) {
     645                        $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE );
     646                }
     647                // set the image’s bit depth to 8 bits
     648                $this->image->setImageDepth( 8 );
     649                // turn off interlacing
     650                $this->image->setInterlaceScheme( Imagick::INTERLACE_NO );
     651                /*
     652                 * In case user wants to fill use extent for it rather than creating a new canvas
     653                 * fill out the bounding box.
     654                 */
     655                if ( $bestfit && $fill && ( $new_width != $columns || $new_height != $rows ) ) {
     656                        $extent_x = 0;
     657                        $extent_y = 0;
     658                        if ( $columns > $new_width ) {
     659                                $extent_x = ( $columns - $new_width ) / 2;
     660                        }
     661                        if ( $rows > $new_height ) {
     662                                $extent_y = ( $rows - $new_height ) / 2;
     663                        }
     664                        $this->image->extentImage( $columns, $rows, 0 - $extent_x, $extent_y );
     665                }
     666                return true;
     667        }
     668
     669
     670        /**
     671         * Strip all profiles except color profiles from an image.
     672         *
     673         * @access public
     674         */
     675        public function strip_profiles() {
     676                foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) {
     677                        if ( $key != 'icc' && $key != 'icm' ) {
     678                                $this->image->removeImageProfile( $key );
     679                        }
     680                }
     681                if ( method_exists( $this, 'deleteImageProperty' ) ) {
     682                        $this->image->deleteImageProperty( 'comment' );
     683                        $this->image->deleteImageProperty( 'Thumb::URI' );
     684                        $this->image->deleteImageProperty( 'Thumb::MTime' );
     685                        $this->image->deleteImageProperty( 'Thumb::Size' );
     686                        $this->image->deleteImageProperty( 'Thumb::Mimetype' );
     687                        $this->image->deleteImageProperty( 'software' );
     688                        $this->image->deleteImageProperty( 'Thumb::Image::Width' );
     689                        $this->image->deleteImageProperty( 'Thumb::Image::Height' );
     690                        $this->image->deleteImageProperty( 'Thumb::Document::Pages' );
     691                } else {
     692                        $this->image->setImageProperty( 'comment', '' );
     693                        $this->image->setImageProperty( 'Thumb::URI', '' );
     694                        $this->image->setImageProperty( 'Thumb::MTime', '' );
     695                        $this->image->setImageProperty( 'Thumb::Size', '' );
     696                        $this->image->setImageProperty( 'Thumb::Mimetype', '' );
     697                        $this->image->setImageProperty( 'software', '' );
     698                        $this->image->setImageProperty( 'Thumb::Image::Width', '' );
     699                        $this->image->setImageProperty( 'Thumb::Image::Height', '' );
     700                        $this->image->setImageProperty( 'Thumb::Document::Pages', '' );
     701                }
     702        }
    533703}
  • src/wp-includes/class-wp-image-editor.php

    diff --git src/wp-includes/class-wp-image-editor.php src/wp-includes/class-wp-image-editor.php
    index adaa884..bb29617 100644
    abstract class WP_Image_Editor { 
    1717        protected $mime_type = null;
    1818        protected $default_mime_type = 'image/jpeg';
    1919        protected $quality = false;
    20         protected $default_quality = 90;
     20        protected $default_quality = 82;
    2121
    2222        /**
    2323         * Each instance handles a single file.
    abstract class WP_Image_Editor { 
    492492                return $extensions[0];
    493493        }
    494494}
    495