| | 257 | // Execute the resize |
| | 258 | $thumb_result = $this->thumbnail_image( $dst_w, $dst_h ); |
| | 259 | if ( is_wp_error( $thumb_result ) ) { |
| | 260 | return $thumb_result; |
| | 261 | } |
| | 262 | |
| | 263 | return $this->update_size( $dst_w, $dst_h ); |
| | 264 | } |
| | 265 | |
| | 266 | /** |
| | 267 | * Efficiently resize the current image |
| | 268 | * |
| | 269 | * This is a WordPress specific implementation of Imagick::thumbnailImage(), |
| | 270 | * which resizes an image to given dimentions and removes any associated profiles. |
| | 271 | * |
| | 272 | * @since 4.5.0 |
| | 273 | * |
| | 274 | * @param int $dst_w The destination width. |
| | 275 | * @param int $dst_h The destination height. |
| | 276 | * @param string $filter_name Optional. The Imagick filter to use when resizing. Default 'FILTER_TRIANGLE'. |
| | 277 | * @param bool $strip_meta Optional. Strip all profiles, excluding color profiles, from the image. Default true. |
| | 278 | * @return bool|WP_Error |
| | 279 | */ |
| | 280 | protected function thumbnail_image( $dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = true ) { |
| | 281 | $allowed_filters = array( |
| | 282 | 'FILTER_POINT', |
| | 283 | 'FILTER_BOX', |
| | 284 | 'FILTER_TRIANGLE', |
| | 285 | 'FILTER_HERMITE', |
| | 286 | 'FILTER_HANNING', |
| | 287 | 'FILTER_HAMMING', |
| | 288 | 'FILTER_BLACKMAN', |
| | 289 | 'FILTER_GAUSSIAN', |
| | 290 | 'FILTER_QUADRATIC', |
| | 291 | 'FILTER_CUBIC', |
| | 292 | 'FILTER_CATROM', |
| | 293 | 'FILTER_MITCHELL', |
| | 294 | 'FILTER_LANCZOS', |
| | 295 | 'FILTER_BESSEL', |
| | 296 | 'FILTER_SINC', |
| | 297 | ); |
| | 298 | |
| | 299 | /** |
| | 300 | * Set the filter value if '$fitler_name' name is in our whitelist and the related |
| | 301 | * Imagick constant is defined or fall back to our default filter. |
| | 302 | */ |
| | 303 | if ( in_array( $filter_name, $allowed_filters ) && defined( 'Imagick::' . $filter_name ) ) { |
| | 304 | $filter = constant( 'Imagick::' . $filter_name ); |
| | 305 | } else { |
| | 306 | $filter = Imagick::FILTER_TRIANGLE; |
| | 307 | } |
| | 308 | |
| | 309 | /** |
| | 310 | * Filter to override stripping metadata from images when they're resized. |
| | 311 | * |
| | 312 | * This filter only applies when resizing using the Imagick editor since GD |
| | 313 | * always strips profiles by default. |
| | 314 | * |
| | 315 | * @since 4.5.0 |
| | 316 | * |
| | 317 | * @param bool $strip_meta Whether to strip image metadata during resizing. Default true. |
| | 318 | */ |
| | 319 | $strip_meta = apply_filters( 'image_strip_meta', $strip_meta ); |
| | 320 | |
| | 321 | // Strip image meta. |
| | 322 | if ( $strip_meta ) { |
| | 323 | $strip_result = $this->strip_meta(); |
| | 324 | |
| | 325 | if ( is_wp_error( $strip_result ) ) { |
| | 326 | return $strip_result; |
| | 327 | } |
| | 328 | } |
| | 329 | |
| | 331 | /* |
| | 332 | * To be more efficient, resample large images to 5x the destination size before resizing |
| | 333 | * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111), |
| | 334 | * unless we would be resampling to a scale smaller than 128x128. |
| | 335 | */ |
| | 336 | $resize_ratio = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] ); |
| | 337 | $sample_factor = 5; |
| | 338 | |
| | 339 | if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) { |
| | 340 | $this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor ); |
| | 341 | } |
| | 342 | |
| | 343 | // Resize to the final output size. |
| | 344 | $this->image->setOption( 'filter:support', '2.0' ); |
| | 345 | $this->image->resizeImage( $dst_w, $dst_h, $filter, 1 ); |
| | 346 | |
| | 347 | // Set appropriate quality settings after resizing. |
| | 348 | if ( 'image/jpeg' == $this->mime_type ) { |
| | 349 | $this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 ); |
| | 350 | $this->image->setOption( 'jpeg:fancy-upsampling', 'off' ); |
| | 351 | } |
| | 352 | |
| | 353 | if ( 'image/png' === $this->mime_type ) { |
| | 354 | $this->image->setOption( 'png:compression-filter', '5' ); |
| | 355 | $this->image->setOption( 'png:compression-level', '9' ); |
| | 356 | $this->image->setOption( 'png:compression-strategy', '1' ); |
| | 357 | $this->image->setOption( 'png:exclude-chunk', 'all' ); |
| | 358 | } |
| | 359 | |
| 257 | | $this->image->scaleImage( $dst_w, $dst_h ); |
| | 366 | if ( method_exists( $this->image, 'getImageAlphaChannel') && $this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED ) { |
| | 367 | $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE ); |
| | 368 | } |
| | 369 | |
| | 370 | // Limit the bit depth of resized images to 8 bits per channel. |
| | 371 | if ( 8 < $this->image->getImageDepth() ) { |
| | 372 | $this->image->setImageDepth( 8 ); |
| | 373 | } |
| | 374 | |
| | 375 | $this->image->setInterlaceScheme( Imagick::INTERLACE_NO ); |
| | 376 | |
| | 654 | |
| | 655 | /** |
| | 656 | * Strip all image meta except color profiles from an image. |
| | 657 | * |
| | 658 | * @access public |
| | 659 | * @since 4.5.0 |
| | 660 | */ |
| | 661 | protected function strip_meta() { |
| | 662 | try { |
| | 663 | // Strip profiles. |
| | 664 | foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) { |
| | 665 | if ( $key != 'icc' && $key != 'icm' ) { |
| | 666 | $this->image->removeImageProfile( $key ); |
| | 667 | } |
| | 668 | } |
| | 669 | |
| | 670 | // Strip image properties. |
| | 671 | if ( method_exists( $this->image, 'deleteImageProperty' ) ) { |
| | 672 | $this->image->deleteImageProperty( 'comment' ); |
| | 673 | $this->image->deleteImageProperty( 'Thumb::URI' ); |
| | 674 | $this->image->deleteImageProperty( 'Thumb::MTime' ); |
| | 675 | $this->image->deleteImageProperty( 'Thumb::Size' ); |
| | 676 | $this->image->deleteImageProperty( 'Thumb::Mimetype' ); |
| | 677 | $this->image->deleteImageProperty( 'software' ); |
| | 678 | $this->image->deleteImageProperty( 'Thumb::Image::Width' ); |
| | 679 | $this->image->deleteImageProperty( 'Thumb::Image::Height' ); |
| | 680 | $this->image->deleteImageProperty( 'Thumb::Document::Pages' ); |
| | 681 | } else { |
| | 682 | $this->image->setImageProperty( 'comment', '' ); |
| | 683 | $this->image->setImageProperty( 'Thumb::URI', '' ); |
| | 684 | $this->image->setImageProperty( 'Thumb::MTime', '' ); |
| | 685 | $this->image->setImageProperty( 'Thumb::Size', '' ); |
| | 686 | $this->image->setImageProperty( 'Thumb::Mimetype', '' ); |
| | 687 | $this->image->setImageProperty( 'software', '' ); |
| | 688 | $this->image->setImageProperty( 'Thumb::Image::Width', '' ); |
| | 689 | $this->image->setImageProperty( 'Thumb::Image::Height', '' ); |
| | 690 | $this->image->setImageProperty( 'Thumb::Document::Pages', '' ); |
| | 691 | } |
| | 692 | } catch ( Excpetion $e ) { |
| | 693 | return new WP_Error( 'image_strip_meta_error', $e->getMessage() ); |
| | 694 | } |
| | 695 | |
| | 696 | return true; |
| | 697 | } |
| | 698 | |