WordPress.org

Make WordPress Core

Ticket #33642: 33642.4.patch

File 33642.4.patch, 7.6 KB (added by joemcgill, 4 years ago)
  • 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..019cbce 100644
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    6262                        'writeimage',
    6363                        'getimageblob',
    6464                        'getimagegeometry',
     65                        'getimagedepth',
    6566                        'getimageformat',
    6667                        'setimageformat',
    6768                        'setimagecompression',
    6869                        'setimagecompressionquality',
     70                        'setimagedepth',
    6971                        'setimagepage',
     72                        'setinterlacescheme',
    7073                        'scaleimage',
    7174                        'cropimage',
    7275                        'rotateimage',
    7376                        'flipimage',
    7477                        'flopimage',
     78                        'unsharpmaskimage',
    7579                );
    7680
    7781                // Now, test for deep requirements within Imagick.
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    249253                        return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
    250254                }
    251255
     256                // Execute the resize
     257                $this->thumbnail_image( $dst_w, $dst_h );
     258
     259                return $this->update_size( $dst_w, $dst_h );
     260        }
     261
     262        /**
     263         * Efficiently resize the current image
     264         *
     265         * This is a WordPress specific implementation of Imagick::thumbnailImage(),
     266         * which resizes an image to given dimentions and removes any associated profiles.
     267         *
     268         * @since 4.5.0
     269         *
     270         * @param int    $dst_w       The destination width.
     271         * @param int    $dst_h       The destination height.
     272         * @param string $filter      Optional. The Imagick filter to use when resizing. Default 'triangle'.
     273         * @param bool   $strip_meta  Optional. Strip all profiles, exluding color profiles, from the image. Default true.
     274         * @return bool|WP_Error
     275         */
     276        protected function thumbnail_image( $dst_w, $dst_h, $filter = 'triangle', $strip_meta = true ) {
     277                $allowed_filters = array(
     278                        'point'     => Imagick::FILTER_POINT,
     279                        'box'       => Imagick::FILTER_BOX,
     280                        'triangle'  => Imagick::FILTER_TRIANGLE,
     281                        'hermite'   => Imagick::FILTER_HERMITE,
     282                        'hanning'   => Imagick::FILTER_HANNING,
     283                        'hamming'   => Imagick::FILTER_HAMMING,
     284                        'blackman'  => Imagick::FILTER_BLACKMAN,
     285                        'gaussian'  => Imagick::FILTER_GAUSSIAN,
     286                        'quadratic' => Imagick::FILTER_QUADRATIC,
     287                        'cubic'     => Imagick::FILTER_CUBIC,
     288                        'catrom'    => Imagick::FILTER_CATROM,
     289                        'mitchell'  => Imagick::FILTER_MITCHELL,
     290                        'lanczos'   => Imagick::FILTER_LANCZOS,
     291                        'bessel'    => Imagick::FILTER_BESSEL,
     292                        'sinc'      => Imagick::FILTER_SINC
     293                );
     294
     295                // Set a default filter if an acceptable one wasn’t passed.
     296                $filter = isset( $filter, $allowed_filters ) ? $allowed_filters[$filter] : Imagick::FILTER_TRIANGLE;
     297
    252298                try {
     299
    253300                        /**
    254                          * @TODO: Thumbnail is more efficient, given a newer version of Imagemagick.
    255                          * $this->image->thumbnailImage( $dst_w, $dst_h );
     301                         * Filter to override stripping metadata from images when they're resized.
     302                         *
     303                         * This filter only applies when resizing using the Imagick editor since GD
     304                         * always strips profiles by default.
     305                         *
     306                         * @since 4.5.0
     307                         *
     308                         * @param bool $strip_meta Whether to strip image metadata during resizing. Default true.
    256309                         */
    257                         $this->image->scaleImage( $dst_w, $dst_h );
     310                        $strip_meta = apply_filters( 'image_strip_meta', $strip_meta );
     311
     312                        // Strip image meta.
     313                        if ( $strip_meta ) {
     314                                $this->strip_meta();
     315                        }
     316
     317                        /*
     318                         * To be more efficient, resample large images to 5x the destination size before resizing
     319                         * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
     320                         * unless we would be resampling to a scale smaller than 128x128.
     321                         */
     322                        $resize_ratio = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] );
     323                        $sample_factor = 5;
     324
     325                        if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) {
     326                                $this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor );
     327                        }
     328
     329                        // Resize to the final output size.
     330                        $this->image->setOption( 'filter:support', '2.0' );
     331                        $this->image->resizeImage( $dst_w, $dst_h, $filter, 1 );
     332
     333                        // Set appropriate quality settings after resizing.
     334                        if ( 'image/jpeg' == $this->mime_type ) {
     335                                $this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 );
     336                                $this->image->setOption( 'jpeg:fancy-upsampling', 'off' );
     337                        }
     338
     339                        if ( 'image/png' === $this->mime_type ) {
     340                                $this->image->setOption( 'png:compression-filter', '5' );
     341                                $this->image->setOption( 'png:compression-level', '9' );
     342                                $this->image->setOption( 'png:compression-strategy', '1' );
     343                                $this->image->setOption( 'png:exclude-chunk', 'all' );
     344                        }
     345
     346                        /**
     347                         * Imagick::getImageAlphaChannel() is only available if Imagick has been
     348                         * compiled against ImageMagick version 6.4.0 or newer.
     349                         */
     350                        if ( method_exists( $this->image, 'getImageAlphaChannel') && $this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED ) {
     351                                $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE );
     352                        }
     353
     354                        // Limit the  bit depth of resized images to 8 bits per channel.
     355                        if ( 8 < $this->image->getImageDepth() ) {
     356                                $this->image->setImageDepth( 8 );
     357                        }
     358
     359                        $this->image->setInterlaceScheme( Imagick::INTERLACE_NO );
     360
    258361                }
    259362                catch ( Exception $e ) {
    260363                        return new WP_Error( 'image_resize_error', $e->getMessage() );
    261364                }
    262 
    263                 return $this->update_size( $dst_w, $dst_h );
    264365        }
    265366
    266367        /**
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    367468                                if ( ! $dst_h )
    368469                                        $dst_h = $src_h;
    369470
    370                                 $this->image->scaleImage( $dst_w, $dst_h );
     471                                $this->thumbnail_image( $dst_w, $dst_h );
    371472                                return $this->update_size();
    372473                        }
    373474                }
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    530631
    531632                return true;
    532633        }
     634
     635        /**
     636         * Strip all image meta except color profiles from an image.
     637         *
     638         * @access public
     639         * @since 4.5.0
     640         */
     641        protected function strip_meta() {
     642                try {
     643                        // Strip profiles.
     644                        foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) {
     645                                if ( $key != 'icc' && $key != 'icm' ) {
     646                                        $this->image->removeImageProfile( $key );
     647                                }
     648                        }
     649
     650                        // Strip image properties.
     651                        if ( method_exists( $this->image, 'deleteImageProperty' ) ) {
     652                                $this->image->deleteImageProperty( 'comment' );
     653                                $this->image->deleteImageProperty( 'Thumb::URI' );
     654                                $this->image->deleteImageProperty( 'Thumb::MTime' );
     655                                $this->image->deleteImageProperty( 'Thumb::Size' );
     656                                $this->image->deleteImageProperty( 'Thumb::Mimetype' );
     657                                $this->image->deleteImageProperty( 'software' );
     658                                $this->image->deleteImageProperty( 'Thumb::Image::Width' );
     659                                $this->image->deleteImageProperty( 'Thumb::Image::Height' );
     660                                $this->image->deleteImageProperty( 'Thumb::Document::Pages' );
     661                        } else {
     662                                $this->image->setImageProperty( 'comment', '' );
     663                                $this->image->setImageProperty( 'Thumb::URI', '' );
     664                                $this->image->setImageProperty( 'Thumb::MTime', '' );
     665                                $this->image->setImageProperty( 'Thumb::Size', '' );
     666                                $this->image->setImageProperty( 'Thumb::Mimetype', '' );
     667                                $this->image->setImageProperty( 'software', '' );
     668                                $this->image->setImageProperty( 'Thumb::Image::Width', '' );
     669                                $this->image->setImageProperty( 'Thumb::Image::Height', '' );
     670                                $this->image->setImageProperty( 'Thumb::Document::Pages', '' );
     671                        }
     672                } catch ( Excpetion $e ) {
     673                        return new WP_Error( 'image_strip_meta_error', $e->getMessage() );
     674                }
     675
     676                return true;
     677        }
     678
    533679}
  • 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 5b6f4ac..bb29617 100644
    abstract class WP_Image_Editor { 
    492492                return $extensions[0];
    493493        }
    494494}
    495