Ticket #6821: 6821.9.3.diff
| File 6821.9.3.diff, 57.4 KB (added by , 13 years ago) |
|---|
-
wp-admin/includes/image-edit.php
diff --git wp-admin/includes/image-edit.php wp-admin/includes/image-edit.php index 8185c20..75b6834 100644
function wp_image_editor($post_id, $msg = false) { 197 197 <?php 198 198 } 199 199 200 function wp_stream_image($image, $mime_type, $post_id) { 201 $image = apply_filters('image_save_pre', $image, $post_id); 202 203 switch ( $mime_type ) { 204 case 'image/jpeg': 205 header('Content-Type: image/jpeg'); 206 return imagejpeg($image, null, 90); 207 case 'image/png': 208 header('Content-Type: image/png'); 209 return imagepng($image); 210 case 'image/gif':211 header('Content-Type: image/gif');212 return imagegif($image); 213 default:200 /** 201 * Streams image in WP_Image_Editor to browser. 202 * Provided for backcompat reasons 203 * 204 * @param WP_Image_Editor $image 205 * @param string $mime_type 206 * @param int $post_id 207 * @return boolean 208 */ 209 function wp_stream_image( $image, $mime_type, $post_id ) { 210 if ( $image instanceof WP_Image_Editor ) { 211 $image = apply_filters('image_editor_save_pre', $image, $post_id); 212 213 if ( is_wp_error( $image->stream( $mime_type ) ) ) 214 214 return false; 215 216 return true; 217 218 } else { 219 _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) ); 220 221 $image = apply_filters('image_save_pre', $image, $post_id); 222 223 switch ( $mime_type ) { 224 case 'image/jpeg': 225 header( 'Content-Type: image/jpeg' ); 226 return imagejpeg( $image, null, 90 ); 227 case 'image/png': 228 header( 'Content-Type: image/png' ); 229 return imagepng( $image ); 230 case 'image/gif': 231 header( 'Content-Type: image/gif' ); 232 return imagegif( $image ); 233 default: 234 return false; 235 } 215 236 } 216 237 } 217 238 218 function wp_save_image_file($filename, $image, $mime_type, $post_id) { 219 $image = apply_filters('image_save_pre', $image, $post_id); 220 $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id); 221 if ( null !== $saved ) 222 return $saved; 223 224 switch ( $mime_type ) { 225 case 'image/jpeg': 226 return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) ); 227 case 'image/png': 228 return imagepng($image, $filename); 229 case 'image/gif': 230 return imagegif($image, $filename); 231 default: 232 return false; 239 /** 240 * Saves Image to File 241 * @TODO: Add mime_type support to WP_Image_Editor 242 * 243 * @param string $filename 244 * @param WP_Image_Editor $image 245 * @param string $mime_type 246 * @param int $post_id 247 * @return boolean 248 */ 249 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) { 250 if ( $image instanceof WP_Image_Editor ) { 251 $image = apply_filters('image_editor_save_pre', $image, $post_id); 252 $saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id); 253 254 if ( null !== $saved ) 255 return $saved; 256 257 return $image->save( $filename, $mime_type ); 258 } else { 259 _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) ); 260 261 $image = apply_filters('image_save_pre', $image, $post_id); 262 $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id); 263 264 if ( null !== $saved ) 265 return $saved; 266 267 switch ( $mime_type ) { 268 case 'image/jpeg': 269 return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) ); 270 case 'image/png': 271 return imagepng( $image, $filename ); 272 case 'image/gif': 273 return imagegif( $image, $filename ); 274 default: 275 return false; 276 } 233 277 } 234 278 } 235 279 … … function _image_get_preview_ratio($w, $h) { 238 282 return $max > 400 ? (400 / $max) : 1; 239 283 } 240 284 285 // @TODO: Returns GD resource, but is NOT public 241 286 function _rotate_image_resource($img, $angle) { 287 _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) ); 242 288 if ( function_exists('imagerotate') ) { 243 289 $rotated = imagerotate($img, $angle, 0); 244 290 if ( is_resource($rotated) ) { … … function _rotate_image_resource($img, $angle) { 249 295 return $img; 250 296 } 251 297 298 /** 299 * @TODO: Only used within image_edit_apply_changes 300 * and receives/returns GD Resource. 301 * Consider removal. 302 * 303 * @param GD_Resource $img 304 * @param boolean $horz 305 * @param boolean $vert 306 * @return GD_Resource 307 */ 252 308 function _flip_image_resource($img, $horz, $vert) { 309 _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) ); 253 310 $w = imagesx($img); 254 311 $h = imagesy($img); 255 312 $dst = wp_imagecreatetruecolor($w, $h); … … function _flip_image_resource($img, $horz, $vert) { 267 324 return $img; 268 325 } 269 326 327 /** 328 * @TODO: Only used within image_edit_apply_changes 329 * and receives/returns GD Resource. 330 * Consider removal. 331 * 332 * @param GD_Resource $img 333 * @param float $x 334 * @param float $y 335 * @param float $w 336 * @param float $h 337 * @return GD_Resource 338 */ 270 339 function _crop_image_resource($img, $x, $y, $w, $h) { 271 340 $dst = wp_imagecreatetruecolor($w, $h); 272 341 if ( is_resource($dst) ) { … … function _crop_image_resource($img, $x, $y, $w, $h) { 278 347 return $img; 279 348 } 280 349 281 function image_edit_apply_changes($img, $changes) { 350 /** 351 * Performs group of changes on Editor specified. 352 * 353 * @param WP_Image_Editor $image 354 * @param type $changes 355 * @return WP_Image_Editor 356 */ 357 function image_edit_apply_changes( $image, $changes ) { 358 if ( is_resource( $image ) ) 359 _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) ); 282 360 283 361 if ( !is_array($changes) ) 284 return $im g;362 return $image; 285 363 286 364 // expand change operations 287 365 foreach ( $changes as $key => $obj ) { … … function image_edit_apply_changes($img, $changes) { 326 404 } 327 405 328 406 // image resource before applying the changes 329 $img = apply_filters('image_edit_before_change', $img, $changes); 407 if ( $image instanceof WP_Image_Editor ) 408 $image = apply_filters('wp_image_editor_before_change', $image, $changes); 409 elseif ( is_resource( $image ) ) 410 $image = apply_filters('image_edit_before_change', $image, $changes); 330 411 331 412 foreach ( $changes as $operation ) { 332 413 switch ( $operation->type ) { 333 414 case 'rotate': 334 if ( $operation->angle != 0 ) 335 $img = _rotate_image_resource($img, $operation->angle); 415 if ( $operation->angle != 0 ) { 416 if ( $image instanceof WP_Image_Editor ) 417 $image->rotate( $operation->angle ); 418 else 419 $image = _rotate_image_resource( $image, $operation->angle ); 420 } 336 421 break; 337 422 case 'flip': 338 423 if ( $operation->axis != 0 ) 339 $img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0); 424 if ( $image instanceof WP_Image_Editor ) 425 $image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); 426 else 427 $image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 ); 340 428 break; 341 429 case 'crop': 342 430 $sel = $operation->sel; 343 $scale = 1 / _image_get_preview_ratio( imagesx($img), imagesy($img) ); // discard preview scaling 344 $img = _crop_image_resource($img, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale); 431 432 if ( $image instanceof WP_Image_Editor ) { 433 $size = $image->get_size(); 434 $w = $size['width']; 435 $h = $size['height']; 436 437 $scale = 1 / _image_get_preview_ratio( $w, $h ); // discard preview scaling 438 $image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale ); 439 } else { 440 $scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // discard preview scaling 441 $image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale ); 442 } 345 443 break; 346 444 } 347 445 } 348 446 349 return $im g;447 return $image; 350 448 } 351 449 352 function stream_preview_image($post_id) { 353 $post = get_post($post_id); 450 451 /** 452 * Streams image in post to browser, along with enqueued changes 453 * in $_REQUEST['history'] 454 * 455 * @param int $post_id 456 * @return boolean 457 */ 458 function stream_preview_image( $post_id ) { 459 $post = get_post( $post_id ); 354 460 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 355 $img = load_image_to_edit( $post_id, $post->post_mime_type, array(400, 400) );356 461 357 if ( !is_resource($img) ) 358 return false; 462 $img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id ) ); 463 464 if ( is_wp_error( $img ) ) 465 return false; 359 466 360 467 $changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null; 361 468 if ( $changes ) 362 $img = image_edit_apply_changes( $img, $changes);469 $img = image_edit_apply_changes( $img, $changes ); 363 470 364 471 // scale the image 365 $w = imagesx($img); 366 $h = imagesy($img); 367 $ratio = _image_get_preview_ratio($w, $h); 472 $size = $img->get_size(); 473 $w = $size['width']; 474 $h = $size['height']; 475 476 $ratio = _image_get_preview_ratio( $w, $h ); 368 477 $w2 = $w * $ratio; 369 478 $h2 = $h * $ratio; 370 479 371 $preview = wp_imagecreatetruecolor($w2, $h2); 372 imagecopyresampled( $preview, $img, 0, 0, 0, 0, $w2, $h2, $w, $h ); 373 wp_stream_image($preview, $post->post_mime_type, $post_id); 480 if ( is_wp_error( $img->resize( $w2, $h2 ) ) ) 481 return false; 374 482 375 imagedestroy($preview); 376 imagedestroy($img); 377 return true; 483 return wp_stream_image( $img, $post->post_mime_type, $post_id ); 378 484 } 379 485 380 486 function wp_restore_image($post_id) { … … function wp_restore_image($post_id) { 450 556 return $msg; 451 557 } 452 558 453 function wp_save_image($post_id) { 559 /** 560 * Saves image to post along with enqueued changes 561 * in $_REQUEST['history'] 562 * 563 * @param int $post_id 564 * @return \stdClass 565 */ 566 function wp_save_image( $post_id ) { 454 567 $return = new stdClass; 455 568 $success = $delete = $scaled = $nocrop = false; 456 $post = get_post($post_id); 457 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 458 $img = load_image_to_edit($post_id, $post->post_mime_type); 569 $post = get_post( $post_id ); 459 570 460 if ( !is_resource($img) ) { 571 $img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id, 'full' ) ); 572 if ( !$img ) { 461 573 $return->error = esc_js( __('Unable to create new image.') ); 462 574 return $return; 463 575 } … … function wp_save_image($post_id) { 468 580 $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do']; 469 581 470 582 if ( $scale && $fwidth > 0 && $fheight > 0 ) { 471 $sX = imagesx($img); 472 $sY = imagesy($img); 583 $size = $img->get_size(); 584 $sX = $size['width']; 585 $sY = $size['height']; 473 586 474 587 // check if it has roughly the same w / h ratio 475 588 $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2); 476 589 if ( -0.1 < $diff && $diff < 0.1 ) { 477 590 // scale the full size image 478 $dst = wp_imagecreatetruecolor($fwidth, $fheight); 479 if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) { 480 imagedestroy($img); 481 $img = $dst; 591 if ( $img->resize( $fwidth, $fheight ) ) 482 592 $scaled = true; 483 }484 593 } 485 594 486 595 if ( !$scaled ) { … … function wp_save_image($post_id) { 551 660 if ( $tag ) 552 661 $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']); 553 662 554 $success = update_attached_file($post_id, $new_path); 663 $success = update_attached_file( $post_id, $new_path ); 664 665 $meta['file'] = _wp_relative_upload_path( $new_path ); 555 666 556 $ meta['file'] = _wp_relative_upload_path($new_path);557 $meta['width'] = imagesx($img);558 $meta['height'] = imagesy($img);667 $size = $img->get_size(); 668 $meta['width'] = $size['width']; 669 $meta['height'] = $size['height']; 559 670 560 671 if ( $success && ('nothumb' == $target || 'all' == $target) ) { 561 672 $sizes = get_intermediate_image_sizes(); … … function wp_save_image($post_id) { 570 681 $success = $delete = $nocrop = true; 571 682 } 572 683 573 if ( isset($sizes) ) { 684 if ( isset( $sizes ) ) { 685 $_sizes = array(); 686 574 687 foreach ( $sizes as $size ) { 575 688 $tag = false; 576 if ( isset( $meta['sizes'][$size]) ) {689 if ( isset( $meta['sizes'][$size] ) ) { 577 690 if ( isset($backup_sizes["$size-orig"]) ) { 578 691 if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] ) 579 692 $tag = "$size-$suffix"; … … function wp_save_image($post_id) { 586 699 } 587 700 588 701 $crop = $nocrop ? false : get_option("{$size}_crop"); 589 $resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop ); 590 591 if ( $resized ) 592 $meta['sizes'][$size] = $resized; 593 else 594 unset($meta['sizes'][$size]); 702 $_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop ); 595 703 } 704 705 $meta['sizes'] = $img->multi_resize( $_sizes ); 596 706 } 597 707 708 unset( $img ); 709 598 710 if ( $success ) { 599 wp_update_attachment_metadata( $post_id, $meta);711 wp_update_attachment_metadata( $post_id, $meta ); 600 712 update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes); 601 713 602 714 if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) { … … function wp_save_image($post_id) { 612 724 613 725 if ( $delete ) { 614 726 $delpath = apply_filters('wp_delete_file', $new_path); 615 @unlink( $delpath);727 @unlink( $delpath ); 616 728 } 617 729 618 imagedestroy($img);619 620 730 $return->msg = esc_js( __('Image saved') ); 621 731 return $return; 622 732 } -
wp-admin/includes/image.php
diff --git wp-admin/includes/image.php wp-admin/includes/image.php index c7638cd..2a5123e 100644
22 22 * @param string $dst_file Optional. The destination file to write to. 23 23 * @return string|WP_Error|false New filepath on success, WP_Error or false on failure. 24 24 */ 25 function wp_crop_image( $src , $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {26 if ( is_numeric( $src ) ) { // Handle int as attachment ID27 $src_file = get_attached_file( $src );25 function wp_crop_image( $src_file, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) { 26 if ( is_numeric( $src_file ) ) { // Handle int as attachment ID 27 $src_file = get_attached_file( $src_file ); 28 28 if ( ! file_exists( $src_file ) ) { 29 29 // If the file doesn't exist, attempt a url fopen on the src link. 30 30 // This can occur with certain file replication plugins. 31 $post = get_post( $src ); 32 $image_type = $post->post_mime_type; 33 $src = load_image_to_edit( $src, $post->post_mime_type, 'full' ); 34 } else { 35 $size = @getimagesize( $src_file ); 36 $image_type = ( $size ) ? $size['mime'] : ''; 37 $src = wp_load_image( $src_file ); 31 $src_file = _load_image_to_edit_path( $src_file, 'full' ); 38 32 } 39 } else {40 $size = @getimagesize( $src );41 $image_type = ( $size ) ? $size['mime'] : '';42 $src = wp_load_image( $src );43 }44 45 if ( ! is_resource( $src ) )46 return new WP_Error( 'error_loading_image', $src, $src_file );47 48 $dst = wp_imagecreatetruecolor( $dst_w, $dst_h );49 50 if ( $src_abs ) {51 $src_w -= $src_x;52 $src_h -= $src_y;53 33 } 54 34 55 if ( function_exists( 'imageantialias' ) ) 56 imageantialias( $dst, true ); 57 58 imagecopyresampled( $dst, $src, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); 35 $editor = WP_Image_Editor::get_instance( $src_file ); 36 $src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs ); 59 37 60 imagedestroy( $src ); // Free up memory 38 if ( is_wp_error( $src ) ) 39 return $src; 61 40 62 41 if ( ! $dst_file ) 63 42 $dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file ); 64 43 65 if ( 'image/png' != $image_type )66 $dst_file = preg_replace( '/\\.[^\\.]+$/', '.jpg', $dst_file );67 68 44 // The directory containing the original file may no longer exist when 69 45 // using a replication plugin. 70 46 wp_mkdir_p( dirname( $dst_file ) ); 71 47 72 48 $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) ); 73 49 74 if ( 'image/png' == $image_type && imagepng( $dst, $dst_file ) ) 75 return $dst_file; 76 elseif ( imagejpeg( $dst, $dst_file, apply_filters( 'jpeg_quality', 90, 'wp_crop_image' ) ) ) 77 return $dst_file; 78 else 79 return false; 50 $result = $editor->save( $dst_file ); 51 return $dst_file; 80 52 } 81 53 82 54 /** … … function wp_generate_attachment_metadata( $attachment_id, $file ) { 121 93 122 94 $sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes ); 123 95 124 foreach ($sizes as $size => $size_data ) { 125 $resized = image_make_intermediate_size( $file, $size_data['width'], $size_data['height'], $size_data['crop'] ); 126 if ( $resized ) 127 $metadata['sizes'][$size] = $resized; 128 } 96 $editor = WP_Image_Editor::get_instance( $file ); 97 $metadata['sizes'] = $editor->multi_resize( $sizes ); 129 98 130 99 // fetch additional metadata from exif/iptc 131 100 $image_meta = wp_read_image_metadata( $file ); -
new file wp-includes/class-wp-image-editor-gd.php
diff --git wp-includes/class-wp-image-editor-gd.php wp-includes/class-wp-image-editor-gd.php new file mode 100644 index 0000000..94c2eec
- + 1 <?php 2 /** 3 * WordPress GD Image Editor 4 * 5 * @package WordPress 6 * @subpackage Image_Editor 7 */ 8 9 /** 10 * WordPress Image Editor Class for Image Manipulation through GD 11 * 12 * @since 3.5.0 13 * @package WordPress 14 * @subpackage Image_Editor 15 * @uses WP_Image_Editor Extends class 16 */ 17 class WP_Image_Editor_GD extends WP_Image_Editor { 18 protected $image = false; // GD Resource 19 20 function __destruct() { 21 if ( $this->image ) { 22 // we don't need the original in memory anymore 23 imagedestroy( $this->image ); 24 } 25 } 26 27 /** 28 * Checks to see if current environment supports GD 29 * 30 * @since 3.5.0 31 * @access protected 32 * 33 * @return boolean 34 */ 35 public static function test() { 36 if ( ! extension_loaded('gd') || ! function_exists('gd_info') ) 37 return false; 38 39 return true; 40 } 41 42 /** 43 * Loads image from $this->file into new GD Resource 44 * 45 * @since 3.5 46 * @access protected 47 * 48 * @return boolean|\WP_Error 49 */ 50 protected function load() { 51 if ( $this->image ) 52 return true; 53 54 if ( ! file_exists( $this->file ) ) 55 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); 56 57 // Set artificially high because GD uses uncompressed images in memory 58 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 59 $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); 60 61 if ( ! is_resource( $this->image ) ) 62 return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file ); 63 64 $size = @getimagesize( $this->file ); 65 if ( ! $size ) 66 return new WP_Error( 'invalid_image', __('Could not read image size.'), $this->file ); 67 68 $this->update_size( $size[0], $size[1] ); 69 $this->mime_type = $size['mime']; 70 71 return true; 72 } 73 74 /** 75 * Sets or updates current image size 76 * 77 * @since 3.5.0 78 * @access protected 79 * 80 * @param int $width 81 * @param int $height 82 */ 83 protected function update_size( $width = false, $height = false ) { 84 if ( ! $width ) 85 $width = imagesx( $this->image ); 86 87 if ( ! $height ) 88 $height = imagesy( $this->image ); 89 90 return parent::update_size( $width, $height ); 91 } 92 93 /** 94 * Checks to see if editor supports mime-type specified 95 * 96 * @since 3.5.0 97 * @access public 98 * 99 * @param string $mime_type 100 * @return boolean 101 */ 102 public static function supports_mime_type( $mime_type ) { 103 $allowed_mime_types = array( 'image/gif', 'image/png', 'image/jpeg' ); 104 105 return in_array( $mime_type, $allowed_mime_types ); 106 } 107 108 /** 109 * Resizes current image. 110 * Wrapper around _resize, since _resize returns a GD Resource 111 * 112 * @param int $max_w 113 * @param int $max_h 114 * @param boolean $crop 115 * @return boolean|WP_Error 116 */ 117 public function resize( $max_w, $max_h, $crop = false ) { 118 if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) 119 return true; 120 121 $resized = $this->_resize( $max_w, $max_h, $crop ); 122 123 if ( is_resource( $resized ) ) { 124 imagedestroy( $this->image ); 125 $this->image = $resized; 126 return true; 127 128 } elseif ( is_wp_error( $resized ) ) 129 return $resized; 130 131 return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file ); 132 } 133 134 protected function _resize( $max_w, $max_h, $crop = false ) { 135 $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); 136 if ( ! $dims ) { 137 return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions'), $this->file ); 138 } 139 list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; 140 141 $resized = wp_imagecreatetruecolor( $dst_w, $dst_h ); 142 imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); 143 144 if ( is_resource( $resized ) ) { 145 $this->update_size( $dst_w, $dst_h ); 146 return $resized; 147 } 148 149 return WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file ); 150 } 151 152 /** 153 * Processes current image and saves to disk 154 * multiple sizes from single source. 155 * 156 * @param array $sizes { {width, height}, ... } 157 * @return array 158 */ 159 public function multi_resize( $sizes ) { 160 $metadata = array(); 161 $orig_size = $this->size; 162 163 foreach ( $sizes as $size => $size_data ) { 164 $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); 165 166 if( ! is_wp_error( $image ) ) { 167 $resized = $this->_save( $image ); 168 169 imagedestroy( $image ); 170 unset( $resized['path'] ); 171 172 if ( ! is_wp_error( $resized ) && $resized ) 173 $metadata[$size] = $resized; 174 } 175 176 $this->size = $orig_size; 177 } 178 179 return $metadata; 180 } 181 182 /** 183 * Crops Image. 184 * 185 * @since 3.5.0 186 * @access public 187 * 188 * @param string|int $src The source file or Attachment ID. 189 * @param int $src_x The start x position to crop from. 190 * @param int $src_y The start y position to crop from. 191 * @param int $src_w The width to crop. 192 * @param int $src_h The height to crop. 193 * @param int $dst_w Optional. The destination width. 194 * @param int $dst_h Optional. The destination height. 195 * @param int $src_abs Optional. If the source crop points are absolute. 196 * @return boolean|WP_Error 197 */ 198 public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { 199 // If destination width/height isn't specified, use same as 200 // width/height from source. 201 if ( ! $dst_w ) 202 $dst_w = $src_w; 203 if ( ! $dst_h ) 204 $dst_h = $src_h; 205 206 $dst = wp_imagecreatetruecolor( $dst_w, $dst_h ); 207 208 if ( $src_abs ) { 209 $src_w -= $src_x; 210 $src_h -= $src_y; 211 } 212 213 if ( function_exists( 'imageantialias' ) ) 214 imageantialias( $dst, true ); 215 216 imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); 217 218 if ( is_resource( $dst ) ) { 219 imagedestroy( $this->image ); 220 $this->image = $dst; 221 $this->update_size( $dst_w, $dst_h ); 222 return true; 223 } 224 225 return WP_Error( 'image_crop_error', __('Image crop failed.'), $this->file ); 226 } 227 228 /** 229 * Rotates current image counter-clockwise by $angle. 230 * Ported from image-edit.php 231 * 232 * @since 3.5.0 233 * @access public 234 * 235 * @param float $angle 236 * @return boolean|WP_Error 237 */ 238 public function rotate( $angle ) { 239 if ( function_exists('imagerotate') ) { 240 $rotated = imagerotate( $this->image, $angle, 0 ); 241 242 if ( is_resource( $rotated ) ) { 243 imagedestroy( $this->image ); 244 $this->image = $rotated; 245 $this->update_size(); 246 return true; 247 } 248 } 249 return WP_Error( 'image_rotate_error', __('Image rotate failed.'), $this->file ); 250 } 251 252 /** 253 * Flips current image 254 * 255 * @param boolean $horz Horizonal Flip 256 * @param boolean $vert Vertical Flip 257 * @returns boolean|WP_Error 258 */ 259 public function flip( $horz, $vert ) { 260 $w = $this->size['width']; 261 $h = $this->size['height']; 262 $dst = wp_imagecreatetruecolor( $w, $h ); 263 264 if ( is_resource( $dst ) ) { 265 $sx = $vert ? ($w - 1) : 0; 266 $sy = $horz ? ($h - 1) : 0; 267 $sw = $vert ? -$w : $w; 268 $sh = $horz ? -$h : $h; 269 270 if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) { 271 imagedestroy( $this->image ); 272 $this->image = $dst; 273 return true; 274 } 275 } 276 return WP_Error( 'image_flip_error', __('Image flip failed.'), $this->file ); 277 } 278 279 /** 280 * Saves current in-memory image to file 281 * 282 * @param string $destfilename 283 * @param string $mime_type 284 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} 285 */ 286 public function save( $filename = null, $mime_type = null ) { 287 $saved = $this->_save( $this->image, $filename, $mime_type ); 288 289 if ( ! is_wp_error( $saved ) ) { 290 $this->file = $saved['path']; 291 $this->mime_type = $saved['mime-type']; 292 } 293 294 return $saved; 295 } 296 297 protected function _save( $image, $filename = null, $mime_type = null ) { 298 list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); 299 300 if ( ! $filename ) 301 $filename = $this->generate_filename( null, null, $extension ); 302 303 if ( 'image/gif' == $mime_type ) { 304 if ( ! $this->make_image( $filename, 'imagegif', array( $image, $filename ) ) ) 305 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); 306 } 307 elseif ( 'image/png' == $mime_type ) { 308 // convert from full colors to index colors, like original PNG. 309 if ( function_exists('imageistruecolor') && ! imageistruecolor( $image ) ) 310 imagetruecolortopalette( $image, false, imagecolorstotal( $image ) ); 311 312 if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) ) 313 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); 314 } 315 elseif ( 'image/jpeg' == $mime_type ) { 316 if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) ) 317 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); 318 } 319 else { 320 return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); 321 } 322 323 // Set correct file permissions 324 $stat = stat( dirname( $filename ) ); 325 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits 326 @ chmod( $filename, $perms ); 327 328 return array( 329 'path' => $filename, 330 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), 331 'width' => $this->size['width'], 332 'height' => $this->size['height'], 333 'mime-type'=> $mime_type, 334 ); 335 } 336 337 /** 338 * Returns stream of current image 339 * 340 * @param string $mime_type 341 */ 342 public function stream( $mime_type = null ) { 343 list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type ); 344 345 switch ( $mime_type ) { 346 case 'image/png': 347 header( 'Content-Type: image/png' ); 348 return imagepng( $this->image ); 349 case 'image/gif': 350 header( 'Content-Type: image/gif' ); 351 return imagegif( $this->image ); 352 default: 353 header( 'Content-Type: image/jpeg' ); 354 return imagejpeg( $this->image, null, $this->quality ); 355 } 356 } 357 } 358 No newline at end of file -
new file wp-includes/class-wp-image-editor-imagick.php
diff --git wp-includes/class-wp-image-editor-imagick.php wp-includes/class-wp-image-editor-imagick.php new file mode 100644 index 0000000..6370a53
- + 1 <?php 2 /** 3 * WordPress Imagick Image Editor 4 * 5 * @package WordPress 6 * @subpackage Image_Editor 7 */ 8 9 /** 10 * WordPress Image Editor Class for Image Manipulation through Imagick PHP Module 11 * 12 * @since 3.5.0 13 * @package WordPress 14 * @subpackage Image_Editor 15 * @uses WP_Image_Editor Extends class 16 */ 17 class WP_Image_Editor_Imagick extends WP_Image_Editor { 18 protected $image = null; // Imagick Object 19 20 function __destruct() { 21 if ( $this->image ) { 22 // we don't need the original in memory anymore 23 $this->image->clear(); 24 $this->image->destroy(); 25 } 26 } 27 28 /** 29 * Checks to see if current environment supports Imagick 30 * 31 * @since 3.5.0 32 * @access protected 33 * 34 * @return boolean 35 */ 36 public static function test() { 37 if ( ! extension_loaded( 'imagick' ) ) 38 return false; 39 40 return true; 41 } 42 43 /** 44 * Loads image from $this->file into new Imagick Object 45 * 46 * @since 3.5.0 47 * @access protected 48 * 49 * @return boolean|WP_Error True if loaded; WP_Error on failure. 50 */ 51 protected function load() { 52 if ( $this->image ) 53 return true; 54 55 if ( ! file_exists( $this->file ) ) 56 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); 57 58 try { 59 $this->image = new Imagick( $this->file ); 60 61 if( ! $this->image->valid() ) 62 return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file); 63 64 // Select the first frame to handle animated GIFs properly 65 $this->image->setIteratorIndex(0); 66 $this->mime_type = $this->get_mime_type( $this->image->getImageFormat() ); 67 } 68 catch ( Exception $e ) { 69 return new WP_Error( 'invalid_image', $e->getMessage(), $this->file ); 70 } 71 72 $updated_size = $this->update_size(); 73 if ( is_wp_error( $updated_size ) ) 74 return $updated_size; 75 76 return $this->set_quality(); 77 } 78 79 /** 80 * Sets Image Compression quality on a 1-100% scale. 81 * 82 * @since 3.5.0 83 * @access public 84 * 85 * @param int $quality Compression Quality. Range: [1,100] 86 * @return boolean|WP_Error 87 */ 88 public function set_quality( $quality = null ) { 89 if ( !$quality ) 90 $quality = $this->quality; 91 92 try { 93 if( 'image/jpeg' == $this->mime_type ) { 94 $this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) ); 95 $this->image->setImageCompression( imagick::COMPRESSION_JPEG ); 96 } 97 else { 98 $this->image->setImageCompressionQuality( $quality ); 99 } 100 } 101 catch ( Exception $e ) { 102 return new WP_Error( 'image_quality_error', $e->getMessage() ); 103 } 104 105 return parent::set_quality( $quality ); 106 } 107 108 /** 109 * Sets or updates current image size 110 * 111 * @since 3.5.0 112 * @access protected 113 * 114 * @param int $width 115 * @param int $height 116 */ 117 protected function update_size( $width = null, $height = null ) { 118 $size = null; 119 if ( !$width || !$height ) { 120 try { 121 $size = $this->image->getImageGeometry(); 122 } 123 catch ( Exception $e ) { 124 return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file ); 125 } 126 } 127 128 if ( ! $width ) 129 $width = $size['width']; 130 131 if ( ! $height ) 132 $height = $size['height']; 133 134 return parent::update_size( $width, $height ); 135 } 136 137 /** 138 * Checks to see if editor supports mime-type specified 139 * 140 * @since 3.5.0 141 * @access public 142 * 143 * @param string $mime_type 144 * @return boolean 145 */ 146 public static function supports_mime_type( $mime_type = null ) { 147 if ( ! $mime_type ) 148 return false; 149 150 $imagick_extension = strtoupper( self::get_extension( $mime_type ) ); 151 152 try { 153 return ( (bool) Imagick::queryFormats( $imagick_extension ) ); 154 } 155 catch ( Exception $e ) { 156 return false; 157 } 158 } 159 160 /** 161 * Resizes current image. 162 * 163 * @param int $max_w 164 * @param int $max_h 165 * @param boolean $crop 166 * @return boolean|WP_Error 167 */ 168 public function resize( $max_w, $max_h, $crop = false ) { 169 if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) 170 return true; 171 172 $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); 173 if ( ! $dims ) 174 return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') ); 175 list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; 176 177 if ( $crop ) { 178 return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h ); 179 } 180 181 try { 182 /** 183 * @TODO: Thumbnail is more efficient, given a newer version of Imagemagick. 184 * $this->image->thumbnailImage( $dst_w, $dst_h ); 185 */ 186 $this->image->scaleImage( $dst_w, $dst_h ); 187 } 188 catch ( Exception $e ) { 189 return new WP_Error( 'image_resize_error', $e->getMessage() ); 190 } 191 192 return $this->update_size( $dst_w, $dst_h ); 193 } 194 195 /** 196 * Processes current image and saves to disk 197 * multiple sizes from single source. 198 * 199 * @param array $sizes 200 * @return array 201 */ 202 public function multi_resize( $sizes ) { 203 $metadata = array(); 204 $orig_size = $this->size; 205 $orig_image = $this->image->getImage(); 206 207 foreach ( $sizes as $size => $size_data ) { 208 if ( ! $this->image ) 209 $this->image = $orig_image->getImage(); 210 211 $resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); 212 213 if( ! is_wp_error( $resize_result ) ) { 214 $resized = $this->_save( $this->image ); 215 216 $this->image->clear(); 217 $this->image->destroy(); 218 $this->image = null; 219 unset( $resized['path'] ); 220 221 if ( ! is_wp_error( $resized ) && $resized ) 222 $metadata[$size] = $resized; 223 } 224 225 $this->size = $orig_size; 226 } 227 228 $this->image = $orig_image; 229 230 return $metadata; 231 } 232 233 /** 234 * Crops Image. 235 * 236 * @since 3.5.0 237 * @access public 238 * 239 * @param string|int $src The source file or Attachment ID. 240 * @param int $src_x The start x position to crop from. 241 * @param int $src_y The start y position to crop from. 242 * @param int $src_w The width to crop. 243 * @param int $src_h The height to crop. 244 * @param int $dst_w Optional. The destination width. 245 * @param int $dst_h Optional. The destination height. 246 * @param int $src_abs Optional. If the source crop points are absolute. 247 * @return boolean|WP_Error 248 */ 249 public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { 250 // Not sure this is compatible. 251 if ( $src_abs ) { 252 $src_w -= $src_x; 253 $src_h -= $src_y; 254 } 255 256 try { 257 $this->image->cropImage( $src_w, $src_h, $src_x, $src_y ); 258 $this->image->setImagePage( $src_w, $src_h, 0, 0); 259 260 if ( $dst_w || $dst_h ) { 261 // If destination width/height isn't specified, use same as 262 // width/height from source. 263 if ( ! $dst_w ) 264 $dst_w = $src_w; 265 if ( ! $dst_h ) 266 $dst_h = $src_h; 267 268 $this->image->scaleImage( $dst_w, $dst_h ); 269 return $this->update_size( $dst_w, $dst_h ); 270 } 271 } 272 catch ( Exception $e ) { 273 return new WP_Error( 'image_crop_error', $e->getMessage() ); 274 } 275 return $this->update_size( $src_w, $src_h ); 276 } 277 278 /** 279 * Rotates current image counter-clockwise by $angle. 280 * 281 * @since 3.5.0 282 * @access public 283 * 284 * @param float $angle 285 * @return boolean|WP_Error 286 */ 287 public function rotate( $angle ) { 288 /** 289 * $angle is 360-$angle because Imagick rotates clockwise 290 * (GD rotates counter-clockwise) 291 */ 292 try { 293 $this->image->rotateImage( new ImagickPixel('none'), 360-$angle ); 294 } 295 catch ( Exception $e ) { 296 return new WP_Error( 'image_rotate_error', $e->getMessage() ); 297 } 298 return $this->update_size(); 299 } 300 301 /** 302 * Flips current image 303 * 304 * @since 3.5.0 305 * @access public 306 * 307 * @param boolean $horz Horizontal Flip 308 * @param boolean $vert Vertical Flip 309 * @returns boolean 310 */ 311 public function flip( $horz, $vert ) { 312 try { 313 if ( $horz ) 314 $this->image->flipImage(); 315 316 if ( $vert ) 317 $this->image->flopImage(); 318 } 319 catch ( Exception $e ) { 320 return new WP_Error( 'image_flip_error', $e->getMessage() ); 321 } 322 return true; 323 } 324 325 /** 326 * Saves current image to file 327 * 328 * @param string $destfilename 329 * @param string $mime_type 330 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} 331 */ 332 public function save( $destfilename = null, $mime_type = null ) { 333 $saved = $this->_save( $this->image, $destfilename, $mime_type ); 334 335 if ( ! is_wp_error( $saved ) ) { 336 $this->file = $saved['path']; 337 $this->mime_type = $saved['mime-type']; 338 339 try { 340 $this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) ); 341 } 342 catch ( Exception $e ) { 343 return new WP_Error( 'image_save_error', $e->getMessage(), $this->file ); 344 } 345 } 346 347 return $saved; 348 } 349 350 protected function _save( $image, $filename = null, $mime_type = null ) { 351 list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); 352 353 if ( ! $filename ) 354 $filename = $this->generate_filename( null, null, $extension ); 355 356 try { 357 // Store initial Format 358 $orig_format = $this->image->getImageFormat(); 359 360 $this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) ); 361 $this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) ); 362 363 // Reset original Format 364 $this->image->setImageFormat( $orig_format ); 365 } 366 catch ( Exception $e ) { 367 return new WP_Error( 'image_save_error', $e->getMessage(), $filename ); 368 } 369 370 // Set correct file permissions 371 $stat = stat( dirname( $filename ) ); 372 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits 373 @ chmod( $filename, $perms ); 374 375 return array( 376 'path' => $filename, 377 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), 378 'width' => $this->size['width'], 379 'height' => $this->size['height'], 380 'mime-type' => $mime_type, 381 ); 382 } 383 384 /** 385 * Streams current image to browser 386 * 387 * @param string $mime_type 388 * @return boolean|WP_Error 389 */ 390 public function stream( $mime_type = null ) { 391 list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type ); 392 393 try { 394 // Temporarily change format for stream 395 $this->image->setImageFormat( strtoupper( $extension ) ); 396 397 // Output stream of image content 398 header( "Content-Type: $mime_type" ); 399 print $this->image->getImageBlob(); 400 401 // Reset Image to original Format 402 $this->image->setImageFormat( $this->get_extension( $this->mime_type ) ); 403 } 404 catch ( Exception $e ) { 405 return new WP_Error( 'image_stream_error', $e->getMessage() ); 406 } 407 408 return true; 409 } 410 } 411 No newline at end of file -
new file wp-includes/class-wp-image-editor.php
diff --git wp-includes/class-wp-image-editor.php wp-includes/class-wp-image-editor.php new file mode 100644 index 0000000..27df919
- + 1 <?php 2 /** 3 * Base WordPress Image Editor 4 * 5 * @package WordPress 6 * @subpackage Image_Editor 7 */ 8 9 /** 10 * Base WordPress Image Editor class for which Editor implementations extend 11 * 12 * @since 3.5.0 13 */ 14 abstract class WP_Image_Editor { 15 protected $file = null; 16 protected $size = null; 17 protected $mime_type = null; 18 protected $default_mime_type = 'image/jpeg'; 19 protected $quality = 90; 20 private static $implementation; 21 22 protected function __construct( $filename ) { 23 $this->file = $filename; 24 } 25 26 /** 27 * Returns a WP_Image_Editor instance and loads file into it. 28 * 29 * @since 3.5.0 30 * @access public 31 * 32 * @param string $path Path to File to Load 33 * @return WP_Image_Editor|WP_Error|boolean 34 */ 35 public final static function get_instance( $path = null ) { 36 $implementation = apply_filters( 'image_editor_class', self::choose_implementation(), $path ); 37 38 if ( $implementation ) { 39 $editor = new $implementation( $path ); 40 $loaded = $editor->load(); 41 42 if ( is_wp_error ( $loaded ) ) 43 return $loaded; 44 45 return $editor; 46 } 47 48 return false; 49 } 50 51 /** 52 * Tests which editors are capable of supporting the request. 53 * 54 * @since 3.5.0 55 * @access private 56 * 57 * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request. 58 */ 59 private final static function choose_implementation() { 60 61 if ( null === self::$implementation ) { 62 $request_order = apply_filters( 'wp_editors', array( 'imagick', 'gd' ) ); 63 64 // Loop over each editor on each request looking for one which will serve this request's needs 65 foreach ( $request_order as $editor ) { 66 $class = 'WP_Image_Editor_' . $editor; 67 68 // Check to see if this editor is a possibility, calls the editor statically 69 if ( ! call_user_func( array( $class, 'test' ) ) ) 70 continue; 71 72 self::$implementation = $class; 73 break; 74 } 75 } 76 return self::$implementation; 77 } 78 79 abstract public static function test(); // returns bool 80 abstract protected function load(); // returns bool|WP_Error 81 abstract public static function supports_mime_type( $mime_type ); // returns bool 82 abstract public function resize( $max_w, $max_h, $crop = false ); 83 abstract public function multi_resize( $sizes ); 84 abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ); 85 abstract public function rotate( $angle ); 86 abstract public function flip( $horz, $vert ); 87 abstract public function save( $destfilename = null, $mime_type = null ); 88 abstract public function stream( $mime_type = null ); 89 90 /** 91 * Gets dimensions of image 92 * 93 * @since 3.5.0 94 * @access public 95 * 96 * @return array {'width'=>int, 'height'=>int} 97 */ 98 public function get_size() { 99 return $this->size; 100 } 101 102 /** 103 * Sets current image size 104 * 105 * @since 3.5.0 106 * @access protected 107 * 108 * @param int $width 109 * @param int $height 110 */ 111 protected function update_size( $width = null, $height = null ) { 112 $this->size = array( 113 'width' => $width, 114 'height' => $height 115 ); 116 return true; 117 } 118 119 /** 120 * Sets Image Compression quality on a 1-100% scale. 121 * 122 * @since 3.5.0 123 * @access public 124 * 125 * @param int $quality Compression Quality. Range: [1,100] 126 * @return boolean 127 */ 128 public function set_quality( $quality ) { 129 $this->quality = apply_filters( 'wp_editor_set_quality', $quality ); 130 131 return ( (bool) $this->quality ); 132 } 133 134 /** 135 * Returns preferred mime-type and extension based on provided 136 * file's extension and mime, or current file's extension and mime. 137 * 138 * Will default to $this->default_mime_type if requested is not supported. 139 * 140 * Provides corrected filename only if filename is provided. 141 * 142 * @since 3.5.0 143 * @access protected 144 * 145 * @param string $filename 146 * @param type $mime_type 147 * @return array { filename|null, extension, mime-type } 148 */ 149 protected function get_output_format( $filename = null, $mime_type = null ) { 150 $new_ext = $file_ext = null; 151 $file_mime = null; 152 153 // By default, assume specified type takes priority 154 if ( $mime_type ) { 155 $new_ext = $this->get_extension( $mime_type ); 156 } 157 158 if ( $filename ) { 159 $file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) ); 160 $file_mime = $this->get_mime_type( $file_ext ); 161 } 162 else { 163 // If no file specified, grab editor's current extension and mime-type. 164 $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) ); 165 $file_mime = $this->mime_type; 166 } 167 168 // Check to see if specified mime-type is the same as type implied by 169 // file extension. If so, prefer extension from file. 170 if ( ! $mime_type || ( $file_mime == $mime_type ) ) { 171 $mime_type = $file_mime; 172 $new_ext = $file_ext; 173 } 174 175 // Double-check that the mime-type selected is supported by the editor. 176 // If not, choose a default instead. 177 if ( ! $this->supports_mime_type( $mime_type ) ) { 178 $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type ); 179 $new_ext = $this->get_extension( $mime_type ); 180 } 181 182 if ( $filename ) { 183 $ext = ''; 184 $info = pathinfo( $filename ); 185 $dir = $info['dirname']; 186 187 if( isset( $info['extension'] ) ) 188 $ext = $info['extension']; 189 190 $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}"; 191 } 192 193 return array( $filename, $new_ext, $mime_type ); 194 } 195 196 /** 197 * Builds an output filename based on current file, and adding proper suffix 198 * 199 * @since 3.5.0 200 * @access public 201 * 202 * @param string $suffix 203 * @param string $dest_path 204 * @param string $extension 205 * @return string filename 206 */ 207 public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) { 208 // $suffix will be appended to the destination filename, just before the extension 209 if ( ! $suffix ) 210 $suffix = $this->get_suffix(); 211 212 $info = pathinfo( $this->file ); 213 $dir = $info['dirname']; 214 $ext = $info['extension']; 215 216 $name = wp_basename( $this->file, ".$ext" ); 217 $new_ext = strtolower( $extension ? $extension : $ext ); 218 219 if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) ) 220 $dir = $_dest_path; 221 222 return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}"; 223 } 224 225 /** 226 * Builds and returns proper suffix for file based on height and width. 227 * 228 * @since 3.5.0 229 * @access public 230 * 231 * @return string suffix 232 */ 233 public function get_suffix() { 234 if ( ! $this->get_size() ) 235 return false; 236 237 return "{$this->size['width']}x{$this->size['height']}"; 238 } 239 240 /** 241 * Either calls editor's save function or handles file as a stream. 242 * 243 * @since 3.5.0 244 * @access protected 245 * 246 * @param string|stream $filename 247 * @param callable $function 248 * @param array $arguments 249 * @return boolean 250 */ 251 protected function make_image( $filename, $function, $arguments ) { 252 $dst_file = $filename; 253 254 if ( $stream = wp_is_stream( $filename ) ) { 255 $filename = null; 256 ob_start(); 257 } 258 259 $result = call_user_func_array( $function, $arguments ); 260 261 if( $result && $stream ) { 262 $contents = ob_get_contents(); 263 264 $fp = fopen( $dst_file, 'w' ); 265 266 if( ! $fp ) 267 return false; 268 269 fwrite( $fp, $contents ); 270 fclose( $fp ); 271 } 272 273 if( $stream ) { 274 ob_end_clean(); 275 } 276 277 return $result; 278 } 279 280 /** 281 * Returns first matched mime-type from extension, 282 * as mapped from wp_get_mime_types() 283 * 284 * @since 3.5.0 285 * @access protected 286 * 287 * @param string $extension 288 * @return string|boolean 289 */ 290 protected static function get_mime_type( $extension = null ) { 291 if ( ! $extension ) 292 return false; 293 294 $mime_types = wp_get_mime_types(); 295 $extensions = array_keys( $mime_types ); 296 297 foreach( $extensions as $_extension ) { 298 if( preg_match("/{$extension}/i", $_extension ) ) { 299 return $mime_types[ $_extension ]; 300 } 301 } 302 303 return false; 304 } 305 306 /** 307 * Returns first matched extension from Mime-type, 308 * as mapped from wp_get_mime_types() 309 * 310 * @since 3.5.0 311 * @access protected 312 * 313 * @param string $mime_type 314 * @return string|boolean 315 */ 316 protected static function get_extension( $mime_type = null ) { 317 $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) ); 318 319 if ( empty( $extensions[0] ) ) 320 return false; 321 322 return $extensions[0]; 323 } 324 } 325 No newline at end of file -
wp-includes/deprecated.php
diff --git wp-includes/deprecated.php wp-includes/deprecated.php index f589017..a9744e8 100644
function _get_post_ancestors( &$post ) { 3206 3206 } 3207 3207 3208 3208 /** 3209 * Load an image from a string, if PHP supports it. 3210 * 3211 * @since 2.1.0 3212 * @deprecated 3.5.0 3213 * @see WP_Image_Editor 3214 * 3215 * @param string $file Filename of the image to load. 3216 * @return resource The resulting image resource on success, Error string on failure. 3217 */ 3218 function wp_load_image( $file ) { 3219 _deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor' ); 3220 3221 if ( is_numeric( $file ) ) 3222 $file = get_attached_file( $file ); 3223 3224 if ( ! file_exists( $file ) ) 3225 return sprintf(__('File “%s” doesn’t exist?'), $file); 3226 3227 if ( ! function_exists('imagecreatefromstring') ) 3228 return __('The GD image library is not installed.'); 3229 3230 // Set artificially high because GD uses uncompressed images in memory 3231 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 3232 $image = imagecreatefromstring( file_get_contents( $file ) ); 3233 3234 if ( !is_resource( $image ) ) 3235 return sprintf(__('File “%s” is not an image.'), $file); 3236 3237 return $image; 3238 } 3239 3240 /** 3241 * Scale down an image to fit a particular size and save a new copy of the image. 3242 * 3243 * The PNG transparency will be preserved using the function, as well as the 3244 * image type. If the file going in is PNG, then the resized image is going to 3245 * be PNG. The only supported image types are PNG, GIF, and JPEG. 3246 * 3247 * Some functionality requires API to exist, so some PHP version may lose out 3248 * support. This is not the fault of WordPress (where functionality is 3249 * downgraded, not actual defects), but of your PHP version. 3250 * 3251 * @since 2.5.0 3252 * @deprecated 3.5.0 3253 * @see WP_Image_Editor 3254 * 3255 * @param string $file Image file path. 3256 * @param int $max_w Maximum width to resize to. 3257 * @param int $max_h Maximum height to resize to. 3258 * @param bool $crop Optional. Whether to crop image or resize. 3259 * @param string $suffix Optional. File suffix. 3260 * @param string $dest_path Optional. New image file path. 3261 * @param int $jpeg_quality Optional, default is 90. Image quality percentage. 3262 * @return mixed WP_Error on failure. String with new destination path. 3263 */ 3264 function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) { 3265 _deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor' ); 3266 3267 $editor = WP_Image_Editor::get_instance( $file ); 3268 if ( is_wp_error( $editor ) ) 3269 return $editor; 3270 $editor->set_quality( $jpeg_quality ); 3271 3272 $resized = $editor->resize( $max_w, $max_h, $crop ); 3273 if ( is_wp_error( $resized ) ) 3274 return $resized; 3275 3276 $dest_file = $editor->generate_filename( $suffix, $dest_path ); 3277 $saved = $editor->save( $dest_file ); 3278 3279 if ( is_wp_error( $saved ) ) 3280 return $saved; 3281 3282 return $dest_file; 3283 } 3284 3285 /** 3209 3286 * Retrieve a single post, based on post ID. 3210 3287 * 3211 3288 * Has categories in 'post_category' property or key. Has tags in 'tags_input' -
wp-includes/functions.php
diff --git wp-includes/functions.php wp-includes/functions.php index 98f52bc..91700a0 100644
function wp_get_original_referer() { 1295 1295 * @return bool Whether the path was created. True if path already exists. 1296 1296 */ 1297 1297 function wp_mkdir_p( $target ) { 1298 $wrapper = null; 1299 1300 // strip the protocol 1301 if( wp_is_stream( $target ) ) { 1302 list( $wrapper, $target ) = explode( '://', $target, 2 ); 1303 } 1304 1298 1305 // from php.net/mkdir user contributed notes 1299 1306 $target = str_replace( '//', '/', $target ); 1300 1307 1308 // put the wrapper back on the target 1309 if( $wrapper !== null ) { 1310 $target = $wrapper . '://' . $target; 1311 } 1312 1301 1313 // safe mode fails with a trailing slash under certain PHP versions. 1302 1314 $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency. 1303 1315 if ( empty($target) ) … … function _device_can_upload() { 3750 3762 } 3751 3763 3752 3764 /** 3765 * Test if a given path is a stream URL 3766 * 3767 * @param string $path The resource path or URL 3768 * @return bool True if the path is a stream URL 3769 */ 3770 function wp_is_stream( $path ) { 3771 $wrappers = stream_get_wrappers(); 3772 $wrappers_re = '(' . join('|', $wrappers) . ')'; 3773 3774 return preg_match( "!^$wrappers_re://!", $path ) === 1; 3775 } 3776 3777 /** 3753 3778 * Test if the supplied date is valid for the Gregorian calendar 3754 3779 * 3755 3780 * @since 3.5.0 -
wp-includes/media.php
diff --git wp-includes/media.php wp-includes/media.php index f36c81c..1fc4383 100644
function get_image_tag($id, $alt, $title, $align, $size='medium') { 236 236 } 237 237 238 238 /** 239 * Load an image from a string, if PHP supports it.240 *241 * @since 2.1.0242 *243 * @param string $file Filename of the image to load.244 * @return resource The resulting image resource on success, Error string on failure.245 */246 function wp_load_image( $file ) {247 if ( is_numeric( $file ) )248 $file = get_attached_file( $file );249 250 if ( ! file_exists( $file ) )251 return sprintf(__('File “%s” doesn’t exist?'), $file);252 253 if ( ! function_exists('imagecreatefromstring') )254 return __('The GD image library is not installed.');255 256 // Set artificially high because GD uses uncompressed images in memory257 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );258 $image = imagecreatefromstring( file_get_contents( $file ) );259 260 if ( !is_resource( $image ) )261 return sprintf(__('File “%s” is not an image.'), $file);262 263 return $image;264 }265 266 /**267 239 * Calculates the new dimensions for a downsampled image. 268 240 * 269 241 * If either width or height are empty, no constraint is applied on … … function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = fal 393 365 } 394 366 395 367 /** 396 * Scale down an image to fit a particular size and save a new copy of the image.397 *398 * The PNG transparency will be preserved using the function, as well as the399 * image type. If the file going in is PNG, then the resized image is going to400 * be PNG. The only supported image types are PNG, GIF, and JPEG.401 *402 * Some functionality requires API to exist, so some PHP version may lose out403 * support. This is not the fault of WordPress (where functionality is404 * downgraded, not actual defects), but of your PHP version.405 *406 * @since 2.5.0407 *408 * @param string $file Image file path.409 * @param int $max_w Maximum width to resize to.410 * @param int $max_h Maximum height to resize to.411 * @param bool $crop Optional. Whether to crop image or resize.412 * @param string $suffix Optional. File suffix.413 * @param string $dest_path Optional. New image file path.414 * @param int $jpeg_quality Optional, default is 90. Image quality percentage.415 * @return mixed WP_Error on failure. String with new destination path.416 */417 function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {418 419 $image = wp_load_image( $file );420 if ( !is_resource( $image ) )421 return new WP_Error( 'error_loading_image', $image, $file );422 423 $size = @getimagesize( $file );424 if ( !$size )425 return new WP_Error('invalid_image', __('Could not read image size'), $file);426 list($orig_w, $orig_h, $orig_type) = $size;427 428 $dims = image_resize_dimensions($orig_w, $orig_h, $max_w, $max_h, $crop);429 if ( !$dims )430 return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );431 list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;432 433 $newimage = wp_imagecreatetruecolor( $dst_w, $dst_h );434 435 imagecopyresampled( $newimage, $image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);436 437 // convert from full colors to index colors, like original PNG.438 if ( IMAGETYPE_PNG == $orig_type && function_exists('imageistruecolor') && !imageistruecolor( $image ) )439 imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) );440 441 // we don't need the original in memory anymore442 imagedestroy( $image );443 444 // $suffix will be appended to the destination filename, just before the extension445 if ( !$suffix )446 $suffix = "{$dst_w}x{$dst_h}";447 448 $info = pathinfo($file);449 $dir = $info['dirname'];450 $ext = $info['extension'];451 $name = wp_basename($file, ".$ext");452 453 if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) )454 $dir = $_dest_path;455 $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";456 457 if ( IMAGETYPE_GIF == $orig_type ) {458 if ( !imagegif( $newimage, $destfilename ) )459 return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));460 } elseif ( IMAGETYPE_PNG == $orig_type ) {461 if ( !imagepng( $newimage, $destfilename ) )462 return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));463 } else {464 // all other formats are converted to jpg465 if ( 'jpg' != $ext && 'jpeg' != $ext )466 $destfilename = "{$dir}/{$name}-{$suffix}.jpg";467 if ( !imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality, 'image_resize' ) ) )468 return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));469 }470 471 imagedestroy( $newimage );472 473 // Set correct file permissions474 $stat = stat( dirname( $destfilename ));475 $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits476 @ chmod( $destfilename, $perms );477 478 return $destfilename;479 }480 481 /**482 368 * Resize an image to make a thumbnail or intermediate size. 483 369 * 484 370 * The returned array has the file size, the image width, and image height. The … … function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $de 493 379 * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize. 494 380 * @return bool|array False, if no image was created. Metadata array on success. 495 381 */ 496 function image_make_intermediate_size( $file, $width, $height, $crop=false) {382 function image_make_intermediate_size( $file, $width, $height, $crop = false ) { 497 383 if ( $width || $height ) { 498 $resized_file = image_resize($file, $width, $height, $crop); 499 if ( !is_wp_error($resized_file) && $resized_file && $info = getimagesize($resized_file) ) { 500 $resized_file = apply_filters('image_make_intermediate_size', $resized_file); 501 return array( 502 'file' => wp_basename( $resized_file ), 503 'width' => $info[0], 504 'height' => $info[1], 505 ); 384 $editor = WP_Image_Editor::get_instance( $file ); 385 386 if ( is_wp_error( $editor->resize( $width, $height, $crop ) ) ); 387 return false; 388 389 $resized_file = $editor->save(); 390 391 if ( ! is_wp_error( $resized_file ) && $resized_file ) { 392 unset( $resized_file['path'] ); 393 return $resized_file; 506 394 } 507 395 } 508 396 return false; … … function gd_edit_image_support($mime_type) { 1047 935 1048 936 /** 1049 937 * Create new GD image resource with transparency support 938 * @TODO: Deprecate if possible. 1050 939 * 1051 940 * @since 2.9.0 1052 941 * -
wp-settings.php
diff --git wp-settings.php wp-settings.php index 0b81e4d..470ed9a 100644
require( ABSPATH . WPINC . '/nav-menu.php' ); 143 143 require( ABSPATH . WPINC . '/nav-menu-template.php' ); 144 144 require( ABSPATH . WPINC . '/admin-bar.php' ); 145 145 146 require( ABSPATH . WPINC . '/class-wp-image-editor.php' ); 147 require( ABSPATH . WPINC . '/class-wp-image-editor-gd.php' ); 148 require( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' ); 149 146 150 // Load multisite-specific files. 147 151 if ( is_multisite() ) { 148 152 require( ABSPATH . WPINC . '/ms-functions.php' );