WordPress.org

Make WordPress Core

Ticket #6821: 6821.3.diff

File 6821.3.diff, 46.3 KB (added by mikeschroder, 7 years ago)

Updated version for chat. To be edited further based on decisions made.

  • wp-admin/includes/image-edit.php

    diff --git wp-admin/includes/image-edit.php wp-admin/includes/image-edit.php
    index d2d6dc2..853cfaf 100644
    function wp_image_editor($post_id, $msg = false) { 
    197197<?php
    198198}
    199199
    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:
    214                         return false;
     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 */
     209function wp_stream_image( $image, $mime_type, $post_id ) {
     210        $image = apply_filters('image_editor_save_pre', $image, $post_id);
     211
     212        if ( ! is_resource( $image ) ) {
     213                $image->stream();
     214
     215    } else {
     216                _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
     217
     218                $image = apply_filters('image_save_pre', $image, $post_id);
     219
     220                switch ( $mime_type ) {
     221                        case 'image/jpeg':
     222                                header( 'Content-Type: image/jpeg' );
     223                                return imagejpeg( $image, null, 90 );
     224                        case 'image/png':
     225                                header( 'Content-Type: image/png' );
     226                                return imagepng( $image );
     227                        case 'image/gif':
     228                                header( 'Content-Type: image/gif' );
     229                                return imagegif( $image );
     230                        default:
     231                                return false;
     232                }
    215233        }
    216234}
    217235
    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;
     236/**
     237 * @TODO: Public function that accepts GD images as input.
     238 * @TODO: Add mime_type support to WP_Image_Editor
     239 *
     240 * @param string $filename
     241 * @param WP_Image_Editor $image
     242 * @param string $mime_type
     243 * @param int $post_id
     244 * @return boolean
     245 */
     246function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
     247        if ( ! is_resource( $image ) ) {
     248                $image = apply_filters('image_editor_save_pre', $image, $post_id);
     249                $saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id);
     250
     251                if ( null !== $saved )
     252                        return $saved;
     253
     254                return $image->save( $filename );
     255        } else {
     256                _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
     257
     258                $image = apply_filters('image_save_pre', $image, $post_id);
     259                $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
     260
     261                if ( null !== $saved )
     262                        return $saved;
     263
     264                switch ( $mime_type ) {
     265                        case 'image/jpeg':
     266                                return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
     267                        case 'image/png':
     268                                return imagepng( $image, $filename );
     269                        case 'image/gif':
     270                                return imagegif( $image, $filename );
     271                        default:
     272                                return false;
     273                }
    233274        }
    234275}
    235276
    function _image_get_preview_ratio($w, $h) { 
    238279        return $max > 400 ? (400 / $max) : 1;
    239280}
    240281
     282// @TODO: Returns GD resource, but is NOT public
    241283function _rotate_image_resource($img, $angle) {
    242284        if ( function_exists('imagerotate') ) {
    243285                $rotated = imagerotate($img, $angle, 0);
    function _rotate_image_resource($img, $angle) { 
    249291        return $img;
    250292}
    251293
     294/**
     295 * @TODO: Only used within image_edit_apply_changes
     296 *                and receives/returns GD Resource.
     297 *                Consider removal.
     298 *
     299 * @param GD_Resource $img
     300 * @param boolean $horz
     301 * @param boolean $vert
     302 * @return GD_Resource
     303 */
    252304function _flip_image_resource($img, $horz, $vert) {
    253305        $w = imagesx($img);
    254306        $h = imagesy($img);
    function _flip_image_resource($img, $horz, $vert) { 
    267319        return $img;
    268320}
    269321
     322/**
     323 * @TODO: Only used within image_edit_apply_changes
     324 *                and receives/returns GD Resource.
     325 *                Consider removal.
     326 *
     327 * @param GD_Resource $img
     328 * @param float $x
     329 * @param float $y
     330 * @param float $w
     331 * @param float $h
     332 * @return GD_Resource
     333 */
    270334function _crop_image_resource($img, $x, $y, $w, $h) {
    271335        $dst = wp_imagecreatetruecolor($w, $h);
    272336        if ( is_resource($dst) ) {
    function _crop_image_resource($img, $x, $y, $w, $h) { 
    278342        return $img;
    279343}
    280344
    281 function image_edit_apply_changes($img, $changes) {
     345/**
     346 * Performs group of changes on Editor specified.
     347 *
     348 * @param WP_Image_Editor $image
     349 * @param type $changes
     350 * @return WP_Image_Editor
     351 */
     352function image_edit_apply_changes( $image, $changes ) {
     353        if ( is_resource( $image ) )
     354                _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
    282355
    283356        if ( !is_array($changes) )
    284                 return $img;
     357                return $image;
    285358
    286359        // expand change operations
    287360        foreach ( $changes as $key => $obj ) {
    function image_edit_apply_changes($img, $changes) { 
    326399        }
    327400
    328401        // image resource before applying the changes
    329         $img = apply_filters('image_edit_before_change', $img, $changes);
     402        if ( ! is_resource( $image ) )
     403                $image = apply_filters('wp_image_editor_before_change', $image, $changes);
     404        else
     405                $image = apply_filters('image_edit_before_change', $image, $changes);
    330406
    331407        foreach ( $changes as $operation ) {
    332408                switch ( $operation->type ) {
    333409                        case 'rotate':
    334                                 if ( $operation->angle != 0 )
    335                                         $img = _rotate_image_resource($img, $operation->angle);
     410                                if ( $operation->angle != 0 ) {
     411                                        if ( ! is_resource( $image ) )
     412                                                $image->rotate( $operation->angle );
     413                                        else
     414                                                $image = _rotate_image_resource( $image, $operation->angle );
     415                                }
    336416                                break;
    337417                        case 'flip':
    338418                                if ( $operation->axis != 0 )
    339                                         $img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0);
     419                                        if ( ! is_resource( $image ) )
     420                                                $image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 );
     421                                        else
     422                                                $image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
    340423                                break;
    341424                        case 'crop':
    342425                                $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);
     426
     427                                if ( ! is_resource( $image ) ) {
     428                                        $size = $image->get_size();
     429                                        $w = $size['width'];
     430                                        $h = $size['height'];
     431
     432                                        $scale = 1 / _image_get_preview_ratio( $w, $h ); // discard preview scaling
     433                                        $image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
     434                                } else {
     435                                        $scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // discard preview scaling
     436                                        $image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
     437                                }
    345438                                break;
    346439                }
    347440        }
    348441
    349         return $img;
     442        return $image;
    350443}
    351444
     445
     446/**
     447 * Streams image in post to browser, along with enqueued changes
     448 * in $_REQUEST['history']
     449 *
     450 * @param int $post_id
     451 * @return boolean
     452 */
    352453function stream_preview_image($post_id) {
    353454        $post = get_post($post_id);
    354455        @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) );
    356456
    357         if ( !is_resource($img) )
    358                 return false;
     457        $img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id ) );
     458
     459    if ( ! $img )
     460        return false;
    359461
    360462        $changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
    361463        if ( $changes )
    362                 $img = image_edit_apply_changes($img, $changes);
     464                $img = image_edit_apply_changes( $img, $changes );
    363465
    364466        // scale the image
    365         $w = imagesx($img);
    366         $h = imagesy($img);
    367         $ratio = _image_get_preview_ratio($w, $h);
     467        $size = $img->get_size();
     468        $w = $size['width'];
     469        $h = $size['height'];
     470
     471        $ratio = _image_get_preview_ratio( $w, $h );
    368472        $w2 = $w * $ratio;
    369473        $h2 = $h * $ratio;
    370474
    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);
    374 
    375         imagedestroy($preview);
    376         imagedestroy($img);
     475        $img->resize( $w2, $h2 );
     476        wp_stream_image( $img, $post->post_mime_type, $post_id );
    377477        return true;
    378478}
    379479
    function wp_restore_image($post_id) { 
    452552        return $msg;
    453553}
    454554
    455 function wp_save_image($post_id) {
     555/**
     556 * Saves image to post along with enqueued changes
     557 * in $_REQUEST['history']
     558 *
     559 * @param int $post_id
     560 * @return \stdClass
     561 */
     562function wp_save_image( $post_id ) {
    456563        $return = new stdClass;
    457564        $success = $delete = $scaled = $nocrop = false;
    458         $post = get_post($post_id);
    459         @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
    460         $img = load_image_to_edit($post_id, $post->post_mime_type);
     565        $post = get_post( $post_id );
    461566
    462         if ( !is_resource($img) ) {
     567        $img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id, 'full' ) );
     568        if ( !$img ) {
    463569                $return->error = esc_js( __('Unable to create new image.') );
    464570                return $return;
    465571        }
    function wp_save_image($post_id) { 
    470576        $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
    471577
    472578        if ( $scale && $fwidth > 0 && $fheight > 0 ) {
    473                 $sX = imagesx($img);
    474                 $sY = imagesy($img);
     579                $size = $img->get_size();
     580                $sX = $size['width'];
     581                $sY = $size['height'];
    475582
    476583                // check if it has roughly the same w / h ratio
    477584                $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
    478585                if ( -0.1 < $diff && $diff < 0.1 ) {
    479586                        // scale the full size image
    480                         $dst = wp_imagecreatetruecolor($fwidth, $fheight);
    481                         if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) {
    482                                 imagedestroy($img);
    483                                 $img = $dst;
     587                        if ( $img->resize( $fwidth, $fheight ) )
    484588                                $scaled = true;
    485                         }
    486589                }
    487590
    488591                if ( !$scaled ) {
    function wp_save_image($post_id) { 
    553656                if ( $tag )
    554657                        $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
    555658
    556                 $success = update_attached_file($post_id, $new_path);
     659                $success = update_attached_file( $post_id, $new_path );
     660
     661                $meta['file'] = _wp_relative_upload_path( $new_path );
    557662
    558                 $meta['file'] = _wp_relative_upload_path($new_path);
    559                 $meta['width'] = imagesx($img);
    560                 $meta['height'] = imagesy($img);
     663                $size = $img->get_size();
     664                $meta['width'] = $size['width'];
     665                $meta['height'] = $size['height'];
    561666
    562667                list ( $uwidth, $uheight ) = wp_constrain_dimensions($meta['width'], $meta['height'], 128, 96);
    563668                $meta['hwstring_small'] = "height='$uheight' width='$uwidth'";
    function wp_save_image($post_id) { 
    575680                $success = $delete = $nocrop = true;
    576681        }
    577682
    578         if ( isset($sizes) ) {
     683        if ( isset( $sizes ) ) {
     684                $_sizes = array();
     685
    579686                foreach ( $sizes as $size ) {
    580687                        $tag = false;
    581                         if ( isset($meta['sizes'][$size]) ) {
     688                        if ( isset( $meta['sizes'][$size] ) ) {
    582689                                if ( isset($backup_sizes["$size-orig"]) ) {
    583690                                        if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
    584691                                                $tag = "$size-$suffix";
    function wp_save_image($post_id) { 
    591698                        }
    592699
    593700                        $crop = $nocrop ? false : get_option("{$size}_crop");
    594                         $resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop );
    595 
    596                         if ( $resized )
    597                                 $meta['sizes'][$size] = $resized;
    598                         else
    599                                 unset($meta['sizes'][$size]);
     701                        $_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
    600702                }
     703
     704                $meta['sizes'] = $img->multi_resize( $_sizes );
    601705        }
    602706
     707        unset( $img );
     708
    603709        if ( $success ) {
    604                 wp_update_attachment_metadata($post_id, $meta);
     710                wp_update_attachment_metadata( $post_id, $meta );
    605711                update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
    606712
    607713                if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
    function wp_save_image($post_id) { 
    617723
    618724        if ( $delete ) {
    619725                $delpath = apply_filters('wp_delete_file', $new_path);
    620                 @unlink($delpath);
     726                @unlink( $delpath );
    621727        }
    622728
    623         imagedestroy($img);
    624 
    625729        $return->msg = esc_js( __('Image saved') );
    626730        return $return;
    627731}
  • wp-admin/includes/image.php

    diff --git wp-admin/includes/image.php wp-admin/includes/image.php
    index 8048387..3205797 100644
    function wp_create_thumbnail( $file, $max_side, $deprecated = '' ) { 
    4343 * @param string $dst_file Optional. The destination file to write to.
    4444 * @return string|WP_Error|false New filepath on success, WP_Error or false on failure.
    4545 */
    46 function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
    47         if ( is_numeric( $src ) ) { // Handle int as attachment ID
    48                 $src_file = get_attached_file( $src );
     46function wp_crop_image( $src_file, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
     47        if ( is_numeric( $src_file ) ) { // Handle int as attachment ID
     48                $src_file = get_attached_file( $src_file );
    4949                if ( ! file_exists( $src_file ) ) {
    5050                        // If the file doesn't exist, attempt a url fopen on the src link.
    5151                        // This can occur with certain file replication plugins.
    52                         $post = get_post( $src );
    53                         $image_type = $post->post_mime_type;
    54                         $src = load_image_to_edit( $src, $post->post_mime_type, 'full' );
    55                 } else {
    56                         $size = @getimagesize( $src_file );
    57                         $image_type = ( $size ) ? $size['mime'] : '';
    58                         $src = wp_load_image( $src_file );
     52                        $src_file = _load_image_to_edit_path( $src_file, 'full' );
    5953                }
    60         } else {
    61                 $size = @getimagesize( $src );
    62                 $image_type = ( $size ) ? $size['mime'] : '';
    63                 $src = wp_load_image( $src );
    64         }
    65 
    66         if ( ! is_resource( $src ) )
    67                 return new WP_Error( 'error_loading_image', $src, $src_file );
    68 
    69         $dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
    70 
    71         if ( $src_abs ) {
    72                 $src_w -= $src_x;
    73                 $src_h -= $src_y;
    7454        }
    7555
    76         if ( function_exists( 'imageantialias' ) )
    77                 imageantialias( $dst, true );
    78 
    79         imagecopyresampled( $dst, $src, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
     56        $editor = WP_Image_Editor::get_instance( $src_file );
     57        $src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
    8058
    81         imagedestroy( $src ); // Free up memory
     59        if ( ! $src )
     60                return new WP_Error( 'error_loading_image', '', $src_file );
    8261
    8362        if ( ! $dst_file )
    8463                $dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file );
    8564
    86         if ( 'image/png' != $image_type )
    87                 $dst_file = preg_replace( '/\\.[^\\.]+$/', '.jpg', $dst_file );
    88 
    8965        // The directory containing the original file may no longer exist when
    9066        // using a replication plugin.
    9167        wp_mkdir_p( dirname( $dst_file ) );
    9268
    9369        $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) );
    9470
    95         if ( 'image/png' == $image_type && imagepng( $dst, $dst_file ) )
    96                 return $dst_file;
    97         elseif ( imagejpeg( $dst, $dst_file, apply_filters( 'jpeg_quality', 90, 'wp_crop_image' ) ) )
    98                 return $dst_file;
    99         else
    100                 return false;
     71        $result = $editor->save( $dst_file );
     72        return $dst_file;
    10173}
    10274
    10375/**
    function wp_generate_attachment_metadata( $attachment_id, $file ) { 
    144116
    145117                $sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes );
    146118
    147                 foreach ($sizes as $size => $size_data ) {
    148                         $resized = image_make_intermediate_size( $file, $size_data['width'], $size_data['height'], $size_data['crop'] );
    149                         if ( $resized )
    150                                 $metadata['sizes'][$size] = $resized;
    151                 }
     119                $editor = WP_Image_Editor::get_instance( $file );
     120                $metadata['sizes'] = $editor->multi_resize( $sizes );
     121                unset( $editor );
    152122
    153123                // fetch additional metadata from exif/iptc
    154124                $image_meta = wp_read_image_metadata( $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..72cb76c
    - +  
     1<?php
     2
     3final class WP_Image_Editor {
     4
     5        public static function get_instance( $path ) {
     6                $implementation = apply_filters( 'image_editor_class', self::choose_implementation(), $path );
     7
     8                if ( $implementation )
     9                        return new $implementation( $path );
     10
     11                return false;
     12        }
     13
     14        /**
     15         * Tests which editors are capable of supporting the request.
     16         *
     17         * @since 3.5.0
     18         * @access private
     19         *
     20         * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request.
     21         */
     22        private static function choose_implementation() {
     23                static $implementation;
     24
     25                if ( null === $implementation ) {
     26                        $request_order = apply_filters( 'wp_editors', array( 'imagick', 'gd' ) );
     27
     28                        // Loop over each editor on each request looking for one which will serve this request's needs
     29                        foreach ( $request_order as $editor ) {
     30                                $class = 'WP_Image_Editor_' . $editor;
     31
     32                                // Check to see if this editor is a possibility, calls the editor statically
     33                                if ( ! call_user_func( array( $class, 'test' ) ) )
     34                                        continue;
     35
     36                                if( ! apply_filters( 'wp_editor_use_' . $editor, true ) )
     37                                        continue;
     38
     39                                $implementation = $class;
     40
     41                                break;
     42                        }
     43                }
     44
     45                return $implementation;
     46        }
     47}
     48 No newline at end of file
  • wp-includes/deprecated.php

    diff --git wp-includes/deprecated.php wp-includes/deprecated.php
    index da8bb1d..241cf8f 100644
    function _get_post_ancestors( &$post ) { 
    32063206}
    32073207
    32083208/**
     3209 * Load an image from a string, if PHP supports it.
     3210 *
     3211 * @since 2.1.0
     3212 * @deprecated 3.5.0
     3213 * @deprecated wp_get_image_for_editing()
     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 */
     3218function wp_load_image( $file ) {
     3219        _deprecated_function( __FUNCTION__, '3.5', 'wp_get_image_for_editing()' );
     3220
     3221        if ( is_numeric( $file ) )
     3222                $file = get_attached_file( $file );
     3223
     3224        if ( ! file_exists( $file ) )
     3225                return sprintf(__('File &#8220;%s&#8221; doesn&#8217;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 &#8220;%s&#8221; 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 * @deprecated wp_get_image_for_editing()
     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 */
     3264function 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 = new WP_Image_Editor_GD( $file );
     3268        $editor->set_quality( $jpeg_quality );
     3269
     3270        $editor->resize( $max_w, $max_h, $crop );
     3271        $editor->save( $editor->generate_filename( $suffix, $dest_path ) );
     3272        unset( $editor );
     3273}
     3274
     3275/**
    32093276 * Retrieve a single post, based on post ID.
    32103277 *
    32113278 * Has categories in 'post_category' property or key. Has tags in 'tags_input'
  • new file wp-includes/editors/class-wp-image-editor-base.php

    diff --git wp-includes/editors/class-wp-image-editor-base.php wp-includes/editors/class-wp-image-editor-base.php
    new file mode 100644
    index 0000000..7f7461e
    - +  
     1<?php
     2
     3abstract class WP_Image_Editor_Base {
     4        protected $file = null;
     5        protected $size = null;
     6        protected $orig_type  = null;
     7        protected $quality = 90;
     8
     9        function __construct( $filename ) {
     10                $this->file = $filename;
     11        }
     12
     13        public static function test() {
     14                return false;
     15        }
     16
     17        protected function load() {
     18                return false;
     19        }
     20
     21        public function get_size() {
     22                if ( ! $this->load() )
     23                        return false;
     24
     25                return $this->size;
     26        }
     27
     28        protected function update_size( $width = null, $height = null ) {
     29                $this->size = array(
     30                        'width' => $width,
     31                        'height' => $height
     32                );
     33        }
     34
     35        public function set_quality( $quality ) {
     36                $this->quality = apply_filters( 'wp_editor_set_quality', $quality );
     37        }
     38
     39        public function generate_filename( $suffix = null, $dest_path = null ) {
     40                if ( ! $this->load() )
     41                        return false;
     42
     43                // $suffix will be appended to the destination filename, just before the extension
     44                $suffix = $this->get_suffix();
     45
     46                $info = pathinfo( $this->file );
     47                $dir  = $info['dirname'];
     48                $ext  = $info['extension'];
     49                $name = wp_basename( $this->file, ".$ext" );
     50
     51                if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
     52                        $dir = $_dest_path;
     53
     54                return "{$dir}/{$name}-{$suffix}.{$ext}";
     55        }
     56
     57        public function get_suffix() {
     58                if ( ! $this->get_size() )
     59                        return false;
     60
     61                return "{$this->size['width']}x{$this->size['height']}";
     62        }
     63}
     64 No newline at end of file
  • new file wp-includes/editors/class-wp-image-editor-gd.php

    diff --git wp-includes/editors/class-wp-image-editor-gd.php wp-includes/editors/class-wp-image-editor-gd.php
    new file mode 100644
    index 0000000..aae23be
    - +  
     1<?php
     2
     3class WP_Image_Editor_GD extends WP_Image_Editor_Base {
     4        private $image = false; // GD Resource
     5
     6        function __destruct() {
     7                if ( $this->image ) {
     8                        // we don't need the original in memory anymore
     9                        imagedestroy( $this->image );
     10                }
     11        }
     12
     13        /**
     14         * Checks to see if GD is available.
     15         *
     16         * @return boolean
     17         */
     18        public static function test() {
     19                if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
     20                        return false;
     21
     22                return true;
     23        }
     24
     25        /**
     26         * Loads image from $this->file into GD Resource
     27         *
     28         * @since 3.5
     29         *
     30         * @return boolean|\WP_Error
     31         */
     32        protected function load() {
     33                if ( $this->image )
     34                        return true;
     35
     36                if ( ! file_exists( $this->file ) )
     37                        return sprintf( __('File &#8220;%s&#8221; doesn&#8217;t exist?'), $this->file );
     38
     39                if ( ! function_exists('imagecreatefromstring') )
     40                        return __('The GD image library is not installed.');
     41
     42                // Set artificially high because GD uses uncompressed images in memory
     43                @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
     44                $this->image = imagecreatefromstring( file_get_contents( $this->file ) );
     45
     46                if ( ! is_resource( $this->image ) )
     47                        return sprintf( __('File &#8220;%s&#8221; is not an image.'), $this->file );
     48
     49                $size = @getimagesize( $this->file );
     50                if ( ! $size )
     51                        return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file );
     52
     53                $this->update_size( $size[0], $size[1] );
     54                $this->orig_type = $size['mime'];
     55
     56                return true;
     57        }
     58
     59        protected function update_size( $width = false, $height = false ) {
     60                if ( ! $this->load() )
     61                        return;
     62
     63                parent::update_size( $width ?: imagesx( $this->image ), $height ?: imagesy( $this->image ) );
     64        }
     65
     66        public function resize( $max_w, $max_h, $crop = false ) {
     67                $resized = $this->_resize( $max_w, $max_h, $crop );
     68
     69                if ( is_resource( $resized ) ) {
     70                        imagedestroy( $this->image );
     71                        $this->image = $resized;
     72
     73                        return true;
     74                }
     75
     76                return false;
     77        }
     78
     79        protected function _resize( $max_w, $max_h, $crop = false ) {
     80                if ( ! $this->load() )
     81                        return;
     82
     83                $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
     84                if ( ! $dims ) {
     85                        return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
     86                }
     87                list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
     88
     89                $resized = wp_imagecreatetruecolor( $dst_w, $dst_h );
     90                imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
     91
     92                if ( is_resource( $resized ) ) {
     93                        $this->update_size( $dst_w, $dst_h );
     94                        return $resized;
     95                }
     96
     97                return false;
     98        }
     99
     100        /**
     101         * Processes current image and saves to disk
     102         * multiple sizes from single source.
     103         *
     104         * @param array $sizes
     105         * @return array
     106         */
     107        public function multi_resize( $sizes ) {
     108                $metadata = array();
     109                if ( ! $this->load() )
     110                        return $metadata;
     111
     112                $orig_size = $this->size;
     113                foreach ( $sizes as $size => $size_data ) {
     114                        $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
     115
     116                        if( ! is_wp_error( $image ) ) {
     117                                $resized = $this->_save( $image );
     118
     119                                imagedestroy( $image );
     120                                unset( $resized['path'] );
     121
     122                                if ( ! is_wp_error( $resized ) && $resized )
     123                                        $metadata[$size] = $resized;
     124                        }
     125
     126                        $this->size = $orig_size;
     127                }
     128
     129                return $metadata;
     130        }
     131
     132        /**
     133         * Ported from image.php
     134         *
     135         * @param float $x
     136         * @param float $y
     137         * @param float $w
     138         * @param float $h
     139         * @return boolean
     140         */
     141        public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
     142                if ( ! $this->load() )
     143                        return;
     144
     145                // If destination width/height isn't specified, use same as
     146                // width/height from source.
     147                $dst_w = $dst_w ?: $src_w;
     148                $dst_h = $dst_h ?: $src_h;
     149                $dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
     150
     151                if ( $src_abs ) {
     152                        $src_w -= $src_x;
     153                        $src_h -= $src_y;
     154                }
     155
     156                if ( function_exists( 'imageantialias' ) )
     157                        imageantialias( $dst, true );
     158
     159                imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
     160
     161                if ( is_resource( $dst ) ) {
     162                        imagedestroy( $this->image );
     163                        $this->image = $dst;
     164                        $this->update_size( $dst_w, $dst_h );
     165                        return true;
     166                }
     167
     168                return false; // @TODO: WP_Error here.
     169        }
     170
     171        /**
     172         * Rotates in memory image by $angle.
     173         * Ported from image-edit.php
     174         *
     175         * @param float $angle
     176         * @return boolean
     177         */
     178        public function rotate( $angle ) {
     179                if ( ! $this->load() )
     180                        return;
     181
     182                if ( function_exists('imagerotate') ) {
     183                        $rotated = imagerotate( $this->image, $angle, 0 );
     184
     185                        if ( is_resource( $rotated ) ) {
     186                                imagedestroy( $this->image );
     187                                $this->image = $rotated;
     188                                $this->update_size();
     189                                return true;
     190                        }
     191                }
     192                return false; // @TODO: WP_Error here.
     193        }
     194
     195        /**
     196         * Ported from image-edit.php
     197         *
     198         * @param boolean $horz
     199         * @param boolean $vert
     200         */
     201        public function flip( $horz, $vert ) {
     202                if ( ! $this->load() )
     203                        return;
     204
     205                $w = $this->size['width'];
     206                $h = $this->size['height'];
     207                $dst = wp_imagecreatetruecolor( $w, $h );
     208
     209                if ( is_resource( $dst ) ) {
     210                        $sx = $vert ? ($w - 1) : 0;
     211                        $sy = $horz ? ($h - 1) : 0;
     212                        $sw = $vert ? -$w : $w;
     213                        $sh = $horz ? -$h : $h;
     214
     215                        if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
     216                                imagedestroy( $this->image );
     217                                $this->image = $dst;
     218                                return true;
     219                        }
     220                }
     221
     222                return false; // @TODO: WP_Error here.
     223        }
     224
     225        /**
     226         * Saves current in-memory image to file
     227         *
     228         * @param string $destfilename
     229         * @return array
     230         */
     231        public function save( $destfilename = null ) {
     232                $saved = $this->_save( $this->image, $destfilename );
     233
     234                if ( ! is_wp_error( $saved ) && $destfilename )
     235                        $this->file = $destfilename;
     236
     237                return $saved;
     238        }
     239
     240        protected function _save( $image, $destfilename = null ) {
     241                if ( ! $this->load() )
     242                        return;
     243
     244                if ( null == $destfilename ) {
     245                        $destfilename = $this->generate_filename();
     246                }
     247
     248                if ( 'image/gif' == $this->orig_type ) {
     249                        if ( ! $this->make_image( 'imagegif', $image, $destfilename ) )
     250                                return new WP_Error( 'image_editor_save_failed', __( 'Image Editor Save Failed' ) );
     251                }
     252                elseif ( 'image/png' == $this->orig_type ) {
     253                        // convert from full colors to index colors, like original PNG.
     254                        if ( function_exists('imageistruecolor') && ! imageistruecolor( $image ) )
     255                                imagetruecolortopalette( $image, false, imagecolorstotal( $image ) );
     256
     257                        if ( ! $this->make_image( 'imagepng', $image, $destfilename ) )
     258                                return new WP_Error( 'image_editor_save_failed', __( 'Image Editor Save Failed' ) );
     259                }
     260                else {
     261                        if ( ! $this->make_image( 'imagejpeg', $image, $destfilename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) )
     262                                return new WP_Error( 'image_editor_save_failed', __( 'Image Editor Save Failed' ) );
     263                }
     264
     265                // Set correct file permissions
     266                $stat = stat( dirname( $destfilename ) );
     267                $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
     268                @ chmod( $destfilename, $perms );
     269
     270                return array(
     271                        'path' => $destfilename,
     272                        'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $destfilename ) ),
     273                        'width' => $this->size['width'],
     274                        'height' => $this->size['height']
     275                );
     276        }
     277
     278        /**
     279         * Returns stream of current image
     280         */
     281        public function stream() {
     282                if ( ! $this->load() )
     283                        return;
     284
     285                switch ( $this->orig_type ) {
     286                        case 'image/jpeg':
     287                                header( 'Content-Type: image/jpeg' );
     288                                return imagejpeg( $this->image, null, $this->quality );
     289                        case 'image/png':
     290                                header( 'Content-Type: image/png' );
     291                                return imagepng( $this->image );
     292                        case 'image/gif':
     293                                header( 'Content-Type: image/gif' );
     294                                return imagegif( $this->image );
     295                        default:
     296                                return false;
     297                }
     298        }
     299
     300        protected function make_image( $function, $image, $filename, $quality = -1, $filters = null ) {
     301                $dst_file = $filename;
     302
     303                if ( $stream = wp_is_stream( $filename ) ) {
     304                        $filename = null;
     305                        ob_start();
     306                }
     307
     308                $result = call_user_func( $function, $image, $filename, $quality, $filters );
     309
     310                if( $result && $stream ) {
     311                        $contents = ob_get_contents();
     312
     313                        $fp = fopen( $dst_file, 'w' );
     314
     315                        if( ! $fp )
     316                                return false;
     317
     318                        fwrite( $fp, $contents );
     319                        fclose( $fp );
     320                }
     321
     322                if( $stream ) {
     323                        ob_end_clean();
     324                }
     325
     326                return $result;
     327        }
     328}
     329 No newline at end of file
  • new file wp-includes/editors/class-wp-image-editor-imagick.php

    diff --git wp-includes/editors/class-wp-image-editor-imagick.php wp-includes/editors/class-wp-image-editor-imagick.php
    new file mode 100644
    index 0000000..f466d7f
    - +  
     1<?php
     2
     3class WP_Image_Editor_Imagick extends WP_Image_Editor_Base {
     4        private $image = null; // Imagick Object
     5
     6        function __destruct() {
     7                if ( $this->image ) {
     8                        // we don't need the original in memory anymore
     9                        $this->image->destroy();
     10                        unset( $this->image );
     11                }
     12        }
     13
     14        public static function test() {
     15                if ( ! extension_loaded('imagick') )
     16                        return false;
     17
     18                return true;
     19        }
     20
     21        protected function load() {
     22                if ( $this->image )
     23                        return true;
     24
     25                if ( ! file_exists( $this->file ) )
     26                        return sprintf( __('File &#8220;%s&#8221; doesn&#8217;t exist?'), $this->file );
     27
     28                try {
     29                        $this->image = new Imagick( $this->file );
     30                        $this->image->setIteratorIndex(0);
     31                }
     32                catch ( Exception $e ) {
     33                        return sprintf(__('File &#8220;%s&#8221; is not an image.'), $this->file);
     34                }
     35
     36                if( ! $this->image->valid() ) {
     37                        return sprintf(__('File &#8220;%s&#8221; is not an image.'), $this->file);
     38                }
     39
     40                $this->update_size();
     41                $this->orig_type  = $this->image->getImageFormat(); // TODO: Wrap in exception handling
     42                if ( ! $this->size )
     43                        return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file );
     44
     45                $this->set_quality();
     46
     47                return true;
     48        }
     49
     50        public function set_quality( $quality = null ) {
     51                $quality = $quality ?: $this->quality;
     52
     53                if( 'JPEG' == $this->orig_type ) {
     54                        $this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) );
     55                        $this->image->setImageCompression( imagick::COMPRESSION_JPEG );
     56                }
     57                else {
     58                        $this->image->setImageCompressionQuality( $quality );
     59                }
     60
     61                return parent::set_quality( $quality );
     62        }
     63
     64        protected function update_size( $width = null, $height = null ) {
     65                if ( ! $this->load() )
     66                        return false;
     67
     68                $size = null;
     69                if ( !$width || !$height ) {
     70                        try {
     71                                $size = $this->image->getImageGeometry();
     72                        }
     73                        catch ( Exception $e ) {
     74                                return sprintf(__('File &#8220;%s&#8221; couldn\'t be checked for size.'), $this->file);
     75                        }
     76                }
     77
     78                parent::update_size( $width ?: $size['width'], $height ?: $size['height'] );
     79        }
     80
     81        public function resize( $max_w, $max_h, $crop = false ) {
     82                if ( ! $this->load() )
     83                        return false;
     84
     85                $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
     86                if ( ! $dims )
     87                        return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
     88                list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
     89
     90                if ( $crop ) {
     91                        return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
     92                }
     93
     94                //$this->image->thumbnailImage( $dst_w, $dst_h );
     95                $this->image->scaleImage( $dst_w, $dst_h );
     96                $this->update_size( $dst_w, $dst_h );
     97
     98                return true;
     99        }
     100
     101        /**
     102         * Processes current image and saves to disk
     103         * multiple sizes from single source.
     104         *
     105         * @param array $sizes
     106         * @return array
     107         */
     108        public function multi_resize( $sizes ) {
     109                $metadata = array();
     110                if ( ! $this->load() )
     111                        return $metadata;
     112
     113                $orig_size = $this->size;
     114                $orig_image = $this->image->getImage();
     115                foreach ( $sizes as $size => $size_data ) {
     116                        if ( ! $this->image )
     117                                $this->image = $orig_image->getImage();
     118
     119                        $resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
     120
     121                        if( ! is_wp_error( $resize_result ) ) {
     122                                $resized = $this->save();
     123
     124                                $this->image->destroy();
     125                                $this->image = null;
     126                                unset( $resized['path'] );
     127
     128                                if ( ! is_wp_error( $resized ) && $resized )
     129                                        $metadata[$size] = $resized;
     130                        }
     131
     132                        $this->size = $orig_size;
     133                }
     134
     135                $this->image = $orig_image;
     136
     137                return $metadata;
     138        }
     139
     140        /**
     141         * Crops image.
     142         *
     143         * @param float $x
     144         * @param float $y
     145         * @param float $w
     146         * @param float $h
     147         * @return boolean
     148         */
     149        public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
     150                if ( ! $this->load() )
     151                        return false;
     152
     153                // Not sure this is compatible.
     154                if ( $src_abs ) {
     155                        $src_w -= $src_x;
     156                        $src_h -= $src_y;
     157                }
     158
     159                $this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
     160                $this->image->setImagePage( $src_w, $src_h, 0, 0);
     161
     162                if ( $dst_w || $dst_h ) {
     163                        // If destination width/height isn't specified, use same as
     164                        // width/height from source.
     165                        $dst_w = $dst_w ?: $src_w;
     166                        $dst_h = $dst_h ?: $src_h;
     167
     168                        $this->image->scaleImage( $dst_w, $dst_h );
     169                        $this->update_size( $dst_w, $dst_h );
     170                        return true;
     171                }
     172
     173                $this->update_size( $src_w, $src_h );
     174                return true;
     175
     176                // @TODO: We need exception handling above  // return false;
     177        }
     178
     179        /**
     180         * Rotates in memory image by $angle.
     181         * Ported from image-edit.php
     182         *
     183         * @param float $angle
     184         * @return boolean
     185         */
     186        public function rotate( $angle ) {
     187                if ( ! $this->load() )
     188                        return false;
     189
     190                /**
     191                 * $angle is 360-$angle because Imagick rotates clockwise
     192                 * (GD rotates counter-clockwise)
     193                 */
     194                try {
     195                        $this->image->rotateImage( new ImagickPixel('none'), 360-$angle );
     196                        $this->update_size();
     197                }
     198                catch ( Exception $e ) {
     199                        return false; // TODO: WP_Error Here.
     200                }
     201        }
     202
     203        /**
     204         * Flips Image
     205         *
     206         * @param boolean $horz
     207         * @param boolean $vert
     208         * @returns boolean
     209         */
     210        public function flip( $horz, $vert ) {
     211                if ( ! $this->load() )
     212                        return false;
     213
     214                try {
     215                        if ( $horz )
     216                                $this->image->flipImage();
     217
     218                        if ( $vert )
     219                                $this->image->flopImage();
     220                }
     221                catch ( Exception $e ) {
     222                        return false; // TODO: WP_Error Here.
     223                }
     224
     225                return true;
     226        }
     227
     228        /**
     229         * Saves current image to file
     230         *
     231         * @param string $destfilename
     232         * @return array
     233         */
     234        public function save( $destfilename = null ) {
     235                $saved = $this->_save( $this->image, $destfilename );
     236
     237                if ( ! is_wp_error( $saved ) && $destfilename )
     238                        $this->file = $destfilename;
     239
     240                return $saved;
     241        }
     242
     243        protected function _save( $image, $destfilename = null ) {
     244                if ( ! $this->load() )
     245                        return false;
     246
     247                if ( null == $destfilename ) {
     248                        $destfilename = $this->generate_filename();
     249                }
     250
     251                if( apply_filters( 'wp_editors_stripimage', true ) ) {
     252                        $image->stripImage();
     253                }
     254
     255                $image->writeImage( $destfilename );
     256
     257                // Set correct file permissions
     258                $stat = stat( dirname( $destfilename ) );
     259                $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
     260                @ chmod( $destfilename, $perms );
     261
     262                return array(
     263                        'path' => $destfilename,
     264                        'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $destfilename ) ),
     265                        'width' => $this->size['width'],
     266                        'height' => $this->size['height']
     267                );
     268        }
     269
     270        /**
     271         * @TODO: Wrap in try and clean up.
     272         * Also, make GIF not stream the last frame :(
     273         *
     274         * @return boolean
     275         */
     276        public function stream() {
     277                if ( ! $this->load() )
     278                        return false;
     279
     280                switch ( $this->orig_type ) {
     281                        case 'JPEG':
     282                                header( 'Content-Type: image/jpeg' );
     283                                break;
     284                        case 'PNG':
     285                                header( 'Content-Type: image/png' );
     286                                break;
     287                        case 'GIF':
     288                                header( 'Content-Type: image/gif' );
     289                                break;
     290                        default:
     291                                return false;
     292                }
     293
     294                print $this->image->getImageBlob();
     295                return true;
     296        }
     297}
     298 No newline at end of file
  • wp-includes/functions.php

    diff --git wp-includes/functions.php wp-includes/functions.php
    index 91314b5..016062f 100644
    function wp_get_original_referer() { 
    12921292 * @return bool Whether the path was created. True if path already exists.
    12931293 */
    12941294function wp_mkdir_p( $target ) {
     1295        $wrapper = null;
     1296
     1297        // strip the protocol
     1298        if( wp_is_stream( $target ) ) {
     1299                list( $wrapper, $target ) = explode( '://', $target, 2 );
     1300        }
     1301
    12951302        // from php.net/mkdir user contributed notes
    12961303        $target = str_replace( '//', '/', $target );
    12971304
     1305        // put the wrapper back on the target
     1306        if( $wrapper !== null ) {
     1307                $target = $wrapper . '://' . $target;
     1308        }
     1309
    12981310        // safe mode fails with a trailing slash under certain PHP versions.
    12991311        $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
    13001312        if ( empty($target) )
    function _device_can_upload() { 
    36843696        return true;
    36853697}
    36863698
     3699/**
     3700 * Test if a given path is a stream URL
     3701 *
     3702 * @param string $path The resource path or URL
     3703 * @return bool True if the path is a stream URL
     3704 */
     3705function wp_is_stream( $path ) {
     3706        $wrappers = stream_get_wrappers();
     3707        $wrappers_re = '(' . join('|', $wrappers) . ')';
     3708
     3709        return preg_match( "!^$wrappers_re://!", $path ) === 1;
     3710}
  • wp-includes/media.php

    diff --git wp-includes/media.php wp-includes/media.php
    index 9f6df8d..8915fa8 100644
    function get_image_tag($id, $alt, $title, $align, $size='medium') { 
    236236}
    237237
    238238/**
    239  * Load an image from a string, if PHP supports it.
    240  *
    241  * @since 2.1.0
    242  *
    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 &#8220;%s&#8221; doesn&#8217;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 memory
    257         @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 &#8220;%s&#8221; is not an image.'), $file);
    262 
    263         return $image;
    264 }
    265 
    266 /**
    267239 * Calculates the new dimensions for a downsampled image.
    268240 *
    269241 * 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 
    393365}
    394366
    395367/**
    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 the
    399  * image type. If the file going in is PNG, then the resized image is going to
    400  * 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 out
    403  * support. This is not the fault of WordPress (where functionality is
    404  * downgraded, not actual defects), but of your PHP version.
    405  *
    406  * @since 2.5.0
    407  *
    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 anymore
    442         imagedestroy( $image );
    443 
    444         // $suffix will be appended to the destination filename, just before the extension
    445         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 jpg
    465                 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 permissions
    474         $stat = stat( dirname( $destfilename ));
    475         $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
    476         @ chmod( $destfilename, $perms );
    477 
    478         return $destfilename;
    479 }
    480 
    481 /**
    482368 * Resize an image to make a thumbnail or intermediate size.
    483369 *
    484370 * 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 
    493379 * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
    494380 * @return bool|array False, if no image was created. Metadata array on success.
    495381 */
    496 function image_make_intermediate_size($file, $width, $height, $crop=false) {
     382function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
    497383        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                $editor->resize( $width, $height, $crop );
     386                $resized_file = $editor->save();
     387
     388                unset( $editor );
     389
     390                if ( ! is_wp_error( $resized_file ) && $resized_file ) {
     391                        unset( $resized_file['path'] );
     392                        return $resized_file;
    506393                }
    507394        }
    508395        return false;
    function gd_edit_image_support($mime_type) { 
    1020907
    1021908/**
    1022909 * Create new GD image resource with transparency support
     910 * @TODO: Deprecate if possible.
    1023911 *
    1024912 * @since 2.9.0
    1025913 *
  • wp-settings.php

    diff --git wp-settings.php wp-settings.php
    index 2db338b..80fd5d5 100644
    require( ABSPATH . WPINC . '/nav-menu.php' ); 
    142142require( ABSPATH . WPINC . '/nav-menu-template.php' );
    143143require( ABSPATH . WPINC . '/admin-bar.php' );
    144144
     145require( ABSPATH . WPINC . '/class-wp-image-editor.php' );
     146require( ABSPATH . WPINC . '/editors/class-wp-image-editor-base.php' );
     147require( ABSPATH . WPINC . '/editors/class-wp-image-editor-gd.php' );
     148require( ABSPATH . WPINC . '/editors/class-wp-image-editor-imagick.php' );
     149
    145150// Load multisite-specific files.
    146151if ( is_multisite() ) {
    147152        require( ABSPATH . WPINC . '/ms-functions.php' );