<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[22094] trunk: Introduce WP_Image_Editor, WP_Image_Editor_Imagick, and WP_Image_Editor_GD.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/22094">22094</a></dd>
<dt>Author</dt> <dd>ryan</dd>
<dt>Date</dt> <dd>2012-10-01 20:59:06 +0000 (Mon, 01 Oct 2012)</dd>
</dl>
<h3>Log Message</h3>
<pre>Introduce WP_Image_Editor, WP_Image_Editor_Imagick, and WP_Image_Editor_GD. Abstracts image editing API and adds support for ImageMagick.
Props DH-Shredder, kurtpayne, markoheijnen
see <a href="http://core.trac.wordpress.org/ticket/6821">#6821</a></pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminincludesimageeditphp">trunk/wp-admin/includes/image-edit.php</a></li>
<li><a href="#trunkwpadminincludesimagephp">trunk/wp-admin/includes/image.php</a></li>
<li><a href="#trunkwpincludesdeprecatedphp">trunk/wp-includes/deprecated.php</a></li>
<li><a href="#trunkwpincludesfunctionsphp">trunk/wp-includes/functions.php</a></li>
<li><a href="#trunkwpincludesmediaphp">trunk/wp-includes/media.php</a></li>
<li><a href="#trunkwpsettingsphp">trunk/wp-settings.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkwpincludesclasswpimageeditorgdphp">trunk/wp-includes/class-wp-image-editor-gd.php</a></li>
<li><a href="#trunkwpincludesclasswpimageeditorimagickphp">trunk/wp-includes/class-wp-image-editor-imagick.php</a></li>
<li><a href="#trunkwpincludesclasswpimageeditorphp">trunk/wp-includes/class-wp-image-editor.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminincludesimageeditphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/image-edit.php (22093 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/image-edit.php        2012-10-01 19:51:23 UTC (rev 22093)
+++ trunk/wp-admin/includes/image-edit.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -197,39 +197,82 @@
</span><span class="cx"> <?php
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function wp_stream_image($image, $mime_type, $post_id) {
-        $image = apply_filters('image_save_pre', $image, $post_id);
</del><ins>+/**
+ * Streams image in WP_Image_Editor to browser.
+ * Provided for backcompat reasons
+ *
+ * @param WP_Image_Editor $image
+ * @param string $mime_type
+ * @param int $post_id
+ * @return boolean
+ */
+function wp_stream_image( $image, $mime_type, $post_id ) {
+        if ( $image instanceof WP_Image_Editor ) {
+                $image = apply_filters('image_editor_save_pre', $image, $post_id);
</ins><span class="cx">
</span><del>-        switch ( $mime_type ) {
-                case 'image/jpeg':
-                        header('Content-Type: image/jpeg');
-                        return imagejpeg($image, null, 90);
-                case 'image/png':
-                        header('Content-Type: image/png');
-                        return imagepng($image);
-                case 'image/gif':
-                        header('Content-Type: image/gif');
-                        return imagegif($image);
-                default:
</del><ins>+                if ( is_wp_error( $image->stream( $mime_type ) ) )
</ins><span class="cx">                         return false;
</span><ins>+
+                return true;
+        } else {
+                _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
+
+                $image = apply_filters('image_save_pre', $image, $post_id);
+
+                switch ( $mime_type ) {
+                        case 'image/jpeg':
+                                header( 'Content-Type: image/jpeg' );
+                                return imagejpeg( $image, null, 90 );
+                        case 'image/png':
+                                header( 'Content-Type: image/png' );
+                                return imagepng( $image );
+                        case 'image/gif':
+                                header( 'Content-Type: image/gif' );
+                                return imagegif( $image );
+                        default:
+                                return false;
+                }
</ins><span class="cx">         }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function wp_save_image_file($filename, $image, $mime_type, $post_id) {
-        $image = apply_filters('image_save_pre', $image, $post_id);
-        $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
-        if ( null !== $saved )
-                return $saved;
</del><ins>+/**
+ * Saves Image to File
+ * @TODO: Add mime_type support to WP_Image_Editor
+ *
+ * @param string $filename
+ * @param WP_Image_Editor $image
+ * @param string $mime_type
+ * @param int $post_id
+ * @return boolean
+ */
+function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
+        if ( $image instanceof WP_Image_Editor ) {
+                $image = apply_filters('image_editor_save_pre', $image, $post_id);
+                $saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id);
</ins><span class="cx">
</span><del>-        switch ( $mime_type ) {
-                case 'image/jpeg':
-                        return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
-                case 'image/png':
-                        return imagepng($image, $filename);
-                case 'image/gif':
-                        return imagegif($image, $filename);
-                default:
-                        return false;
</del><ins>+                if ( null !== $saved )
+                        return $saved;
+
+                return $image->save( $filename, $mime_type );
+        } else {
+                _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
+
+                $image = apply_filters('image_save_pre', $image, $post_id);
+                $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id);
+
+                if ( null !== $saved )
+                        return $saved;
+
+                switch ( $mime_type ) {
+                        case 'image/jpeg':
+                                return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
+                        case 'image/png':
+                                return imagepng( $image, $filename );
+                        case 'image/gif':
+                                return imagegif( $image, $filename );
+                        default:
+                                return false;
+                }
</ins><span class="cx">         }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -238,7 +281,9 @@
</span><span class="cx">         return $max > 400 ? (400 / $max) : 1;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+// @TODO: Returns GD resource, but is NOT public
</ins><span class="cx"> function _rotate_image_resource($img, $angle) {
</span><ins>+        _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
</ins><span class="cx">         if ( function_exists('imagerotate') ) {
</span><span class="cx">                 $rotated = imagerotate($img, $angle, 0);
</span><span class="cx">                 if ( is_resource($rotated) ) {
</span><span class="lines">@@ -249,7 +294,18 @@
</span><span class="cx">         return $img;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/**
+ * @TODO: Only used within image_edit_apply_changes
+ *                 and receives/returns GD Resource.
+ *                 Consider removal.
+ *
+ * @param GD_Resource $img
+ * @param boolean $horz
+ * @param boolean $vert
+ * @return GD_Resource
+ */
</ins><span class="cx"> function _flip_image_resource($img, $horz, $vert) {
</span><ins>+        _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
</ins><span class="cx">         $w = imagesx($img);
</span><span class="cx">         $h = imagesy($img);
</span><span class="cx">         $dst = wp_imagecreatetruecolor($w, $h);
</span><span class="lines">@@ -267,6 +323,18 @@
</span><span class="cx">         return $img;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/**
+ * @TODO: Only used within image_edit_apply_changes
+ *                 and receives/returns GD Resource.
+ *                 Consider removal.
+ *
+ * @param GD_Resource $img
+ * @param float $x
+ * @param float $y
+ * @param float $w
+ * @param float $h
+ * @return GD_Resource
+ */
</ins><span class="cx"> function _crop_image_resource($img, $x, $y, $w, $h) {
</span><span class="cx">         $dst = wp_imagecreatetruecolor($w, $h);
</span><span class="cx">         if ( is_resource($dst) ) {
</span><span class="lines">@@ -278,10 +346,19 @@
</span><span class="cx">         return $img;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function image_edit_apply_changes($img, $changes) {
</del><ins>+/**
+ * Performs group of changes on Editor specified.
+ *
+ * @param WP_Image_Editor $image
+ * @param type $changes
+ * @return WP_Image_Editor
+ */
+function image_edit_apply_changes( $image, $changes ) {
+        if ( is_resource( $image ) )
+                _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
</ins><span class="cx">
</span><span class="cx">         if ( !is_array($changes) )
</span><del>-                return $img;
</del><ins>+                return $image;
</ins><span class="cx">
</span><span class="cx">         // expand change operations
</span><span class="cx">         foreach ( $changes as $key => $obj ) {
</span><span class="lines">@@ -326,55 +403,83 @@
</span><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         // image resource before applying the changes
</span><del>-        $img = apply_filters('image_edit_before_change', $img, $changes);
</del><ins>+        if ( $image instanceof WP_Image_Editor )
+                $image = apply_filters('wp_image_editor_before_change', $image, $changes);
+        elseif ( is_resource( $image ) )
+                $image = apply_filters('image_edit_before_change', $image, $changes);
</ins><span class="cx">
</span><span class="cx">         foreach ( $changes as $operation ) {
</span><span class="cx">                 switch ( $operation->type ) {
</span><span class="cx">                         case 'rotate':
</span><del>-                                if ( $operation->angle != 0 )
-                                        $img = _rotate_image_resource($img, $operation->angle);
</del><ins>+                                if ( $operation->angle != 0 ) {
+                                        if ( $image instanceof WP_Image_Editor )
+                                                $image->rotate( $operation->angle );
+                                        else
+                                                $image = _rotate_image_resource( $image, $operation->angle );
+                                }
</ins><span class="cx">                                 break;
</span><span class="cx">                         case 'flip':
</span><span class="cx">                                 if ( $operation->axis != 0 )
</span><del>-                                        $img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0);
</del><ins>+                                        if ( $image instanceof WP_Image_Editor )
+                                                $image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 );
+                                        else
+                                                $image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
</ins><span class="cx">                                 break;
</span><span class="cx">                         case 'crop':
</span><span class="cx">                                 $sel = $operation->sel;
</span><del>-                                $scale = 1 / _image_get_preview_ratio( imagesx($img), imagesy($img) ); // discard preview scaling
-                                $img = _crop_image_resource($img, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale);
</del><ins>+
+                                if ( $image instanceof WP_Image_Editor ) {
+                                        $size = $image->get_size();
+                                        $w = $size['width'];
+                                        $h = $size['height'];
+
+                                        $scale = 1 / _image_get_preview_ratio( $w, $h ); // discard preview scaling
+                                        $image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
+                                } else {
+                                        $scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // discard preview scaling
+                                        $image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
+                                }
</ins><span class="cx">                                 break;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">
</span><del>-        return $img;
</del><ins>+        return $image;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-function stream_preview_image($post_id) {
-        $post = get_post($post_id);
</del><ins>+
+/**
+ * Streams image in post to browser, along with enqueued changes
+ * in $_REQUEST['history']
+ *
+ * @param int $post_id
+ * @return boolean
+ */
+function stream_preview_image( $post_id ) {
+        $post = get_post( $post_id );
</ins><span class="cx">         @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
</span><del>-        $img = load_image_to_edit( $post_id, $post->post_mime_type, array(400, 400) );
</del><span class="cx">
</span><del>-        if ( !is_resource($img) )
-                return false;
</del><ins>+        $img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id ) );
</ins><span class="cx">
</span><ins>+ if ( is_wp_error( $img ) )
+ return false;
+
</ins><span class="cx">         $changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
</span><span class="cx">         if ( $changes )
</span><del>-                $img = image_edit_apply_changes($img, $changes);
</del><ins>+                $img = image_edit_apply_changes( $img, $changes );
</ins><span class="cx">
</span><span class="cx">         // scale the image
</span><del>-        $w = imagesx($img);
-        $h = imagesy($img);
-        $ratio = _image_get_preview_ratio($w, $h);
</del><ins>+        $size = $img->get_size();
+        $w = $size['width'];
+        $h = $size['height'];
+
+        $ratio = _image_get_preview_ratio( $w, $h );
</ins><span class="cx">         $w2 = $w * $ratio;
</span><span class="cx">         $h2 = $h * $ratio;
</span><span class="cx">
</span><del>-        $preview = wp_imagecreatetruecolor($w2, $h2);
-        imagecopyresampled( $preview, $img, 0, 0, 0, 0, $w2, $h2, $w, $h );
-        wp_stream_image($preview, $post->post_mime_type, $post_id);
</del><ins>+        if ( is_wp_error( $img->resize( $w2, $h2 ) ) )
+                return false;
</ins><span class="cx">
</span><del>-        imagedestroy($preview);
-        imagedestroy($img);
-        return true;
</del><ins>+        return wp_stream_image( $img, $post->post_mime_type, $post_id );
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> function wp_restore_image($post_id) {
</span><span class="lines">@@ -450,14 +555,20 @@
</span><span class="cx">         return $msg;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function wp_save_image($post_id) {
</del><ins>+/**
+ * Saves image to post along with enqueued changes
+ * in $_REQUEST['history']
+ *
+ * @param int $post_id
+ * @return \stdClass
+ */
+function wp_save_image( $post_id ) {
</ins><span class="cx">         $return = new stdClass;
</span><span class="cx">         $success = $delete = $scaled = $nocrop = false;
</span><del>-        $post = get_post($post_id);
-        @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
-        $img = load_image_to_edit($post_id, $post->post_mime_type);
</del><ins>+        $post = get_post( $post_id );
</ins><span class="cx">
</span><del>-        if ( !is_resource($img) ) {
</del><ins>+        $img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id, 'full' ) );
+        if ( !$img ) {
</ins><span class="cx">                 $return->error = esc_js( __('Unable to create new image.') );
</span><span class="cx">                 return $return;
</span><span class="cx">         }
</span><span class="lines">@@ -468,19 +579,16 @@
</span><span class="cx">         $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
</span><span class="cx">
</span><span class="cx">         if ( $scale && $fwidth > 0 && $fheight > 0 ) {
</span><del>-                $sX = imagesx($img);
-                $sY = imagesy($img);
</del><ins>+                $size = $img->get_size();
+                $sX = $size['width'];
+                $sY = $size['height'];
</ins><span class="cx">
</span><span class="cx">                 // check if it has roughly the same w / h ratio
</span><span class="cx">                 $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
</span><span class="cx">                 if ( -0.1 < $diff && $diff < 0.1 ) {
</span><span class="cx">                         // scale the full size image
</span><del>-                        $dst = wp_imagecreatetruecolor($fwidth, $fheight);
-                        if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) {
-                                imagedestroy($img);
-                                $img = $dst;
</del><ins>+                        if ( $img->resize( $fwidth, $fheight ) )
</ins><span class="cx">                                 $scaled = true;
</span><del>-                        }
</del><span class="cx">                 }
</span><span class="cx">
</span><span class="cx">                 if ( !$scaled ) {
</span><span class="lines">@@ -551,12 +659,14 @@
</span><span class="cx">                 if ( $tag )
</span><span class="cx">                         $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
</span><span class="cx">
</span><del>-                $success = update_attached_file($post_id, $new_path);
</del><ins>+                $success = update_attached_file( $post_id, $new_path );
</ins><span class="cx">
</span><del>-                $meta['file'] = _wp_relative_upload_path($new_path);
-                $meta['width'] = imagesx($img);
-                $meta['height'] = imagesy($img);
</del><ins>+                $meta['file'] = _wp_relative_upload_path( $new_path );
</ins><span class="cx">
</span><ins>+                $size = $img->get_size();
+                $meta['width'] = $size['width'];
+                $meta['height'] = $size['height'];
+
</ins><span class="cx">                 if ( $success && ('nothumb' == $target || 'all' == $target) ) {
</span><span class="cx">                         $sizes = get_intermediate_image_sizes();
</span><span class="cx">                         if ( 'nothumb' == $target )
</span><span class="lines">@@ -570,10 +680,12 @@
</span><span class="cx">                 $success = $delete = $nocrop = true;
</span><span class="cx">         }
</span><span class="cx">
</span><del>-        if ( isset($sizes) ) {
</del><ins>+        if ( isset( $sizes ) ) {
+                $_sizes = array();
+
</ins><span class="cx">                 foreach ( $sizes as $size ) {
</span><span class="cx">                         $tag = false;
</span><del>-                        if ( isset($meta['sizes'][$size]) ) {
</del><ins>+                        if ( isset( $meta['sizes'][$size] ) ) {
</ins><span class="cx">                                 if ( isset($backup_sizes["$size-orig"]) ) {
</span><span class="cx">                                         if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
</span><span class="cx">                                                 $tag = "$size-$suffix";
</span><span class="lines">@@ -586,17 +698,16 @@
</span><span class="cx">                         }
</span><span class="cx">
</span><span class="cx">                         $crop = $nocrop ? false : get_option("{$size}_crop");
</span><del>-                        $resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop );
</del><ins>+                        $_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
+                }
</ins><span class="cx">
</span><del>-                        if ( $resized )
-                                $meta['sizes'][$size] = $resized;
-                        else
-                                unset($meta['sizes'][$size]);
-                }
</del><ins>+                $meta['sizes'] = $img->multi_resize( $_sizes );
</ins><span class="cx">         }
</span><span class="cx">
</span><ins>+        unset( $img );
+
</ins><span class="cx">         if ( $success ) {
</span><del>-                wp_update_attachment_metadata($post_id, $meta);
</del><ins>+                wp_update_attachment_metadata( $post_id, $meta );
</ins><span class="cx">                 update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
</span><span class="cx">
</span><span class="cx">                 if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
</span><span class="lines">@@ -612,11 +723,9 @@
</span><span class="cx">
</span><span class="cx">         if ( $delete ) {
</span><span class="cx">                 $delpath = apply_filters('wp_delete_file', $new_path);
</span><del>-                @unlink($delpath);
</del><ins>+                @unlink( $delpath );
</ins><span class="cx">         }
</span><span class="cx">
</span><del>-        imagedestroy($img);
-
</del><span class="cx">         $return->msg = esc_js( __('Image saved') );
</span><span class="cx">         return $return;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkwpadminincludesimagephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/image.php (22093 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/image.php        2012-10-01 19:51:23 UTC (rev 22093)
+++ trunk/wp-admin/includes/image.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -22,61 +22,33 @@
</span><span class="cx"> * @param string $dst_file Optional. The destination file to write to.
</span><span class="cx"> * @return string|WP_Error|false New filepath on success, WP_Error or false on failure.
</span><span class="cx"> */
</span><del>-function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
-        if ( is_numeric( $src ) ) { // Handle int as attachment ID
-                $src_file = get_attached_file( $src );
</del><ins>+function wp_crop_image( $src_file, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
+        if ( is_numeric( $src_file ) ) { // Handle int as attachment ID
+                $src_file = get_attached_file( $src_file );
</ins><span class="cx">                 if ( ! file_exists( $src_file ) ) {
</span><span class="cx">                         // If the file doesn't exist, attempt a url fopen on the src link.
</span><span class="cx">                         // This can occur with certain file replication plugins.
</span><del>-                        $post = get_post( $src );
-                        $image_type = $post->post_mime_type;
-                        $src = load_image_to_edit( $src, $post->post_mime_type, 'full' );
-                } else {
-                        $size = @getimagesize( $src_file );
-                        $image_type = ( $size ) ? $size['mime'] : '';
-                        $src = wp_load_image( $src_file );
</del><ins>+                        $src_file = _load_image_to_edit_path( $src_file, 'full' );
</ins><span class="cx">                 }
</span><del>-        } else {
-                $size = @getimagesize( $src );
-                $image_type = ( $size ) ? $size['mime'] : '';
-                $src = wp_load_image( $src );
</del><span class="cx">         }
</span><span class="cx">
</span><del>-        if ( ! is_resource( $src ) )
-                return new WP_Error( 'error_loading_image', $src, $src_file );
</del><ins>+        $editor = WP_Image_Editor::get_instance( $src_file );
+        $src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
</ins><span class="cx">
</span><del>-        $dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
</del><ins>+        if ( is_wp_error( $src ) )
+                return $src;
</ins><span class="cx">
</span><del>-        if ( $src_abs ) {
-                $src_w -= $src_x;
-                $src_h -= $src_y;
-        }
-
-        if ( function_exists( 'imageantialias' ) )
-                imageantialias( $dst, true );
-
-        imagecopyresampled( $dst, $src, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
-
-        imagedestroy( $src ); // Free up memory
-
</del><span class="cx">         if ( ! $dst_file )
</span><span class="cx">                 $dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file );
</span><span class="cx">
</span><del>-        if ( 'image/png' != $image_type )
-                $dst_file = preg_replace( '/\\.[^\\.]+$/', '.jpg', $dst_file );
-
</del><span class="cx">         // The directory containing the original file may no longer exist when
</span><span class="cx">         // using a replication plugin.
</span><span class="cx">         wp_mkdir_p( dirname( $dst_file ) );
</span><span class="cx">
</span><span class="cx">         $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) );
</span><span class="cx">
</span><del>-        if ( 'image/png' == $image_type && imagepng( $dst, $dst_file ) )
-                return $dst_file;
-        elseif ( imagejpeg( $dst, $dst_file, apply_filters( 'jpeg_quality', 90, 'wp_crop_image' ) ) )
-                return $dst_file;
-        else
-                return false;
</del><ins>+        $result = $editor->save( $dst_file );
+        return $dst_file;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="lines">@@ -121,11 +93,8 @@
</span><span class="cx">
</span><span class="cx">                 $sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes );
</span><span class="cx">
</span><del>-                foreach ($sizes as $size => $size_data ) {
-                        $resized = image_make_intermediate_size( $file, $size_data['width'], $size_data['height'], $size_data['crop'] );
-                        if ( $resized )
-                                $metadata['sizes'][$size] = $resized;
-                }
</del><ins>+                $editor = WP_Image_Editor::get_instance( $file );
+                $metadata['sizes'] = $editor->multi_resize( $sizes );
</ins><span class="cx">
</span><span class="cx">                 // fetch additional metadata from exif/iptc
</span><span class="cx">                 $image_meta = wp_read_image_metadata( $file );
</span></span></pre></div>
<a id="trunkwpincludesclasswpimageeditorgdphp"></a>
<div class="addfile"><h4>Added: trunk/wp-includes/class-wp-image-editor-gd.php (0 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-image-editor-gd.php         (rev 0)
+++ trunk/wp-includes/class-wp-image-editor-gd.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -0,0 +1,357 @@
</span><ins>+<?php
+/**
+ * WordPress GD Image Editor
+ *
+ * @package WordPress
+ * @subpackage Image_Editor
+ */
+
+/**
+ * WordPress Image Editor Class for Image Manipulation through GD
+ *
+ * @since 3.5.0
+ * @package WordPress
+ * @subpackage Image_Editor
+ * @uses WP_Image_Editor Extends class
+ */
+class WP_Image_Editor_GD extends WP_Image_Editor {
+        protected $image = false; // GD Resource
+
+        function __destruct() {
+                if ( $this->image ) {
+                        // we don't need the original in memory anymore
+                        imagedestroy( $this->image );
+                }
+        }
+
+        /**
+         * Checks to see if current environment supports GD
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @return boolean
+         */
+        public static function test() {
+                if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
+                        return false;
+
+                return true;
+        }
+
+        /**
+         * Loads image from $this->file into new GD Resource
+         *
+         * @since 3.5
+         * @access protected
+         *
+         * @return boolean|\WP_Error
+         */
+        protected function load() {
+                if ( $this->image )
+                        return true;
+
+                if ( ! file_exists( $this->file ) )
+                        return new WP_Error( 'error_loading_image', __('File doesn&#8217;t exist?'), $this->file );
+
+                // Set artificially high because GD uses uncompressed images in memory
+                @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
+                $this->image = @imagecreatefromstring( file_get_contents( $this->file ) );
+
+                if ( ! is_resource( $this->image ) )
+                        return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file );
+
+                $size = @getimagesize( $this->file );
+                if ( ! $size )
+                        return new WP_Error( 'invalid_image', __('Could not read image size.'), $this->file );
+
+                $this->update_size( $size[0], $size[1] );
+                $this->mime_type = $size['mime'];
+
+                return true;
+        }
+
+        /**
+         * Sets or updates current image size
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param int $width
+         * @param int $height
+         */
+        protected function update_size( $width = false, $height = false ) {
+                if ( ! $width )
+                        $width = imagesx( $this->image );
+
+                if ( ! $height )
+                        $height = imagesy( $this->image );
+
+                return parent::update_size( $width, $height );
+        }
+
+        /**
+         * Checks to see if editor supports mime-type specified
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param string $mime_type
+         * @return boolean
+         */
+        public static function supports_mime_type( $mime_type ) {
+                $allowed_mime_types = array( 'image/gif', 'image/png', 'image/jpeg' );
+
+                return in_array( $mime_type, $allowed_mime_types );
+        }
+
+        /**
+         * Resizes current image.
+         * Wrapper around _resize, since _resize returns a GD Resource
+         *
+         * @param int $max_w
+         * @param int $max_h
+         * @param boolean $crop
+         * @return boolean|WP_Error
+         */
+        public function resize( $max_w, $max_h, $crop = false ) {
+                if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
+                        return true;
+
+                $resized = $this->_resize( $max_w, $max_h, $crop );
+
+                if ( is_resource( $resized ) ) {
+                        imagedestroy( $this->image );
+                        $this->image = $resized;
+                        return true;
+
+                } elseif ( is_wp_error( $resized ) )
+                        return $resized;
+
+                return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file );
+        }
+
+        protected function _resize( $max_w, $max_h, $crop = false ) {
+                $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
+                if ( ! $dims ) {
+                        return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions'), $this->file );
+                }
+                list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
+
+                $resized = wp_imagecreatetruecolor( $dst_w, $dst_h );
+                imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
+
+                if ( is_resource( $resized ) ) {
+                        $this->update_size( $dst_w, $dst_h );
+                        return $resized;
+                }
+
+                return WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file );
+        }
+
+        /**
+         * Processes current image and saves to disk
+         * multiple sizes from single source.
+         *
+         * @param array $sizes { {width, height}, ... }
+         * @return array
+         */
+        public function multi_resize( $sizes ) {
+                $metadata = array();
+                $orig_size = $this->size;
+
+                foreach ( $sizes as $size => $size_data ) {
+                        $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
+
+                        if( ! is_wp_error( $image ) ) {
+                                $resized = $this->_save( $image );
+
+                                imagedestroy( $image );
+                                unset( $resized['path'] );
+
+                                if ( ! is_wp_error( $resized ) && $resized )
+                                        $metadata[$size] = $resized;
+                        }
+
+                        $this->size = $orig_size;
+                }
+
+                return $metadata;
+        }
+
+        /**
+         * Crops Image.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param string|int $src The source file or Attachment ID.
+         * @param int $src_x The start x position to crop from.
+         * @param int $src_y The start y position to crop from.
+         * @param int $src_w The width to crop.
+         * @param int $src_h The height to crop.
+         * @param int $dst_w Optional. The destination width.
+         * @param int $dst_h Optional. The destination height.
+         * @param int $src_abs Optional. If the source crop points are absolute.
+         * @return boolean|WP_Error
+         */
+        public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
+                // If destination width/height isn't specified, use same as
+                // width/height from source.
+                if ( ! $dst_w )
+                        $dst_w = $src_w;
+                if ( ! $dst_h )
+                        $dst_h = $src_h;
+
+                $dst = wp_imagecreatetruecolor( $dst_w, $dst_h );
+
+                if ( $src_abs ) {
+                        $src_w -= $src_x;
+                        $src_h -= $src_y;
+                }
+
+                if ( function_exists( 'imageantialias' ) )
+                        imageantialias( $dst, true );
+
+                imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
+
+                if ( is_resource( $dst ) ) {
+                        imagedestroy( $this->image );
+                        $this->image = $dst;
+                        $this->update_size( $dst_w, $dst_h );
+                        return true;
+                }
+
+                return WP_Error( 'image_crop_error', __('Image crop failed.'), $this->file );
+        }
+
+        /**
+         * Rotates current image counter-clockwise by $angle.
+         * Ported from image-edit.php
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param float $angle
+         * @return boolean|WP_Error
+         */
+        public function rotate( $angle ) {
+                if ( function_exists('imagerotate') ) {
+                        $rotated = imagerotate( $this->image, $angle, 0 );
+
+                        if ( is_resource( $rotated ) ) {
+                                imagedestroy( $this->image );
+                                $this->image = $rotated;
+                                $this->update_size();
+                                return true;
+                        }
+                }
+                return WP_Error( 'image_rotate_error', __('Image rotate failed.'), $this->file );
+        }
+
+        /**
+         * Flips current image
+         *
+         * @param boolean $horz Horizonal Flip
+         * @param boolean $vert Vertical Flip
+         * @returns boolean|WP_Error
+         */
+        public function flip( $horz, $vert ) {
+                $w = $this->size['width'];
+                $h = $this->size['height'];
+                $dst = wp_imagecreatetruecolor( $w, $h );
+
+                if ( is_resource( $dst ) ) {
+                        $sx = $vert ? ($w - 1) : 0;
+                        $sy = $horz ? ($h - 1) : 0;
+                        $sw = $vert ? -$w : $w;
+                        $sh = $horz ? -$h : $h;
+
+                        if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
+                                imagedestroy( $this->image );
+                                $this->image = $dst;
+                                return true;
+                        }
+                }
+                return WP_Error( 'image_flip_error', __('Image flip failed.'), $this->file );
+        }
+
+        /**
+         * Saves current in-memory image to file
+         *
+         * @param string $destfilename
+         * @param string $mime_type
+         * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
+         */
+        public function save( $filename = null, $mime_type = null ) {
+                $saved = $this->_save( $this->image, $filename, $mime_type );
+
+                if ( ! is_wp_error( $saved ) ) {
+                        $this->file = $saved['path'];
+                        $this->mime_type = $saved['mime-type'];
+                }
+
+                return $saved;
+        }
+
+        protected function _save( $image, $filename = null, $mime_type = null ) {
+                list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
+
+                if ( ! $filename )
+                        $filename = $this->generate_filename( null, null, $extension );
+
+                if ( 'image/gif' == $mime_type ) {
+                        if ( ! $this->make_image( $filename, 'imagegif', array( $image, $filename ) ) )
+                                return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
+                }
+                elseif ( 'image/png' == $mime_type ) {
+                        // convert from full colors to index colors, like original PNG.
+                        if ( function_exists('imageistruecolor') && ! imageistruecolor( $image ) )
+                                imagetruecolortopalette( $image, false, imagecolorstotal( $image ) );
+
+                        if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) )
+                                return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
+                }
+                elseif ( 'image/jpeg' == $mime_type ) {
+                        if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) )
+                                return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
+                }
+                else {
+                        return new WP_Error( 'image_save_error', __('Image Editor Save Failed') );
+                }
+
+                // Set correct file permissions
+                $stat = stat( dirname( $filename ) );
+                $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
+                @ chmod( $filename, $perms );
+
+                return array(
+                        'path' => $filename,
+                        'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
+                        'width' => $this->size['width'],
+                        'height' => $this->size['height'],
+                        'mime-type'=> $mime_type,
+                );
+        }
+
+        /**
+         * Returns stream of current image
+         *
+         * @param string $mime_type
+         */
+        public function stream( $mime_type = null ) {
+                list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
+
+                switch ( $mime_type ) {
+                        case 'image/png':
+                                header( 'Content-Type: image/png' );
+                                return imagepng( $this->image );
+                        case 'image/gif':
+                                header( 'Content-Type: image/gif' );
+                                return imagegif( $this->image );
+                        default:
+                                header( 'Content-Type: image/jpeg' );
+                                return imagejpeg( $this->image, null, $this->quality );
+                }
+        }
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/wp-includes/class-wp-image-editor-gd.php
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkwpincludesclasswpimageeditorimagickphp"></a>
<div class="addfile"><h4>Added: trunk/wp-includes/class-wp-image-editor-imagick.php (0 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-image-editor-imagick.php         (rev 0)
+++ trunk/wp-includes/class-wp-image-editor-imagick.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -0,0 +1,410 @@
</span><ins>+<?php
+/**
+ * WordPress Imagick Image Editor
+ *
+ * @package WordPress
+ * @subpackage Image_Editor
+ */
+
+/**
+ * WordPress Image Editor Class for Image Manipulation through Imagick PHP Module
+ *
+ * @since 3.5.0
+ * @package WordPress
+ * @subpackage Image_Editor
+ * @uses WP_Image_Editor Extends class
+ */
+class WP_Image_Editor_Imagick extends WP_Image_Editor {
+        protected $image = null; // Imagick Object
+
+        function __destruct() {
+                if ( $this->image ) {
+                        // we don't need the original in memory anymore
+                        $this->image->clear();
+                        $this->image->destroy();
+                }
+        }
+
+        /**
+         * Checks to see if current environment supports Imagick
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @return boolean
+         */
+        public static function test() {
+                if ( ! extension_loaded( 'imagick' ) )
+                        return false;
+
+                return true;
+        }
+
+        /**
+         * Loads image from $this->file into new Imagick Object
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @return boolean|WP_Error True if loaded; WP_Error on failure.
+         */
+        protected function load() {
+                if ( $this->image )
+                        return true;
+
+                if ( ! file_exists( $this->file ) )
+                        return new WP_Error( 'error_loading_image', __('File doesn&#8217;t exist?'), $this->file );
+
+                try {
+                        $this->image = new Imagick( $this->file );
+
+                        if( ! $this->image->valid() )
+                                return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file);
+
+                        // Select the first frame to handle animated GIFs properly
+                        $this->image->setIteratorIndex(0);
+                        $this->mime_type = $this->get_mime_type( $this->image->getImageFormat() );
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'invalid_image', $e->getMessage(), $this->file );
+                }
+
+                $updated_size = $this->update_size();
+                if ( is_wp_error( $updated_size ) )
+                                return $updated_size;
+
+                return $this->set_quality();
+        }
+
+        /**
+         * Sets Image Compression quality on a 1-100% scale.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param int $quality Compression Quality. Range: [1,100]
+         * @return boolean|WP_Error
+         */
+        public function set_quality( $quality = null ) {
+                if ( !$quality )
+                        $quality = $this->quality;
+
+                try {
+                        if( 'image/jpeg' == $this->mime_type ) {
+                                $this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) );
+                                $this->image->setImageCompression( imagick::COMPRESSION_JPEG );
+                        }
+                        else {
+                                $this->image->setImageCompressionQuality( $quality );
+                        }
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_quality_error', $e->getMessage() );
+                }
+
+                return parent::set_quality( $quality );
+        }
+
+        /**
+         * Sets or updates current image size
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param int $width
+         * @param int $height
+         */
+        protected function update_size( $width = null, $height = null ) {
+                $size = null;
+                if ( !$width || !$height ) {
+                        try {
+                                $size = $this->image->getImageGeometry();
+                        }
+                        catch ( Exception $e ) {
+                                return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file );
+                        }
+                }
+
+                if ( ! $width )
+                        $width = $size['width'];
+
+                if ( ! $height )
+                        $height = $size['height'];
+
+                return parent::update_size( $width, $height );
+        }
+
+        /**
+         * Checks to see if editor supports mime-type specified
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param string $mime_type
+         * @return boolean
+         */
+        public static function supports_mime_type( $mime_type = null ) {
+                if ( ! $mime_type )
+                        return false;
+
+                $imagick_extension = strtoupper( self::get_extension( $mime_type ) );
+
+                try {
+                        return ( (bool) Imagick::queryFormats( $imagick_extension ) );
+                }
+                catch ( Exception $e ) {
+                        return false;
+                }
+        }
+
+        /**
+         * Resizes current image.
+         *
+         * @param int $max_w
+         * @param int $max_h
+         * @param boolean $crop
+         * @return boolean|WP_Error
+         */
+        public function resize( $max_w, $max_h, $crop = false ) {
+                if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) )
+                        return true;
+
+                $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
+                if ( ! $dims )
+                        return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
+                list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
+
+                if ( $crop ) {
+                        return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
+                }
+
+                try {
+                        /**
+                         * @TODO: Thumbnail is more efficient, given a newer version of Imagemagick.
+                         * $this->image->thumbnailImage( $dst_w, $dst_h );
+                         */
+                        $this->image->scaleImage( $dst_w, $dst_h );
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_resize_error', $e->getMessage() );
+                }
+
+                return $this->update_size( $dst_w, $dst_h );
+        }
+
+        /**
+         * Processes current image and saves to disk
+         * multiple sizes from single source.
+         *
+         * @param array $sizes
+         * @return array
+         */
+        public function multi_resize( $sizes ) {
+                $metadata = array();
+                $orig_size = $this->size;
+                $orig_image = $this->image->getImage();
+
+                foreach ( $sizes as $size => $size_data ) {
+                        if ( ! $this->image )
+                                $this->image = $orig_image->getImage();
+
+                        $resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
+
+                        if( ! is_wp_error( $resize_result ) ) {
+                                $resized = $this->_save( $this->image );
+
+                                $this->image->clear();
+                                $this->image->destroy();
+                                $this->image = null;
+                                unset( $resized['path'] );
+
+                                if ( ! is_wp_error( $resized ) && $resized )
+                                        $metadata[$size] = $resized;
+                        }
+
+                        $this->size = $orig_size;
+                }
+
+                $this->image = $orig_image;
+
+                return $metadata;
+        }
+
+        /**
+         * Crops Image.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param string|int $src The source file or Attachment ID.
+         * @param int $src_x The start x position to crop from.
+         * @param int $src_y The start y position to crop from.
+         * @param int $src_w The width to crop.
+         * @param int $src_h The height to crop.
+         * @param int $dst_w Optional. The destination width.
+         * @param int $dst_h Optional. The destination height.
+         * @param int $src_abs Optional. If the source crop points are absolute.
+         * @return boolean|WP_Error
+         */
+        public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
+                // Not sure this is compatible.
+                if ( $src_abs ) {
+                        $src_w -= $src_x;
+                        $src_h -= $src_y;
+                }
+
+                try {
+                        $this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
+                        $this->image->setImagePage( $src_w, $src_h, 0, 0);
+
+                        if ( $dst_w || $dst_h ) {
+                                // If destination width/height isn't specified, use same as
+                                // width/height from source.
+                                if ( ! $dst_w )
+                                        $dst_w = $src_w;
+                                if ( ! $dst_h )
+                                        $dst_h = $src_h;
+
+                                $this->image->scaleImage( $dst_w, $dst_h );
+                                return $this->update_size( $dst_w, $dst_h );
+                        }
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_crop_error', $e->getMessage() );
+                }
+                return $this->update_size( $src_w, $src_h );
+        }
+
+        /**
+         * Rotates current image counter-clockwise by $angle.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param float $angle
+         * @return boolean|WP_Error
+         */
+        public function rotate( $angle ) {
+                /**
+                 * $angle is 360-$angle because Imagick rotates clockwise
+                 * (GD rotates counter-clockwise)
+                 */
+                try {
+                        $this->image->rotateImage( new ImagickPixel('none'), 360-$angle );
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_rotate_error', $e->getMessage() );
+                }
+                return $this->update_size();
+        }
+
+        /**
+         * Flips current image
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param boolean $horz Horizontal Flip
+         * @param boolean $vert Vertical Flip
+         * @returns boolean
+         */
+        public function flip( $horz, $vert ) {
+                try {
+                        if ( $horz )
+                                $this->image->flipImage();
+
+                        if ( $vert )
+                                $this->image->flopImage();
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_flip_error', $e->getMessage() );
+                }
+                return true;
+        }
+
+        /**
+         * Saves current image to file
+         *
+         * @param string $destfilename
+         * @param string $mime_type
+         * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
+         */
+        public function save( $destfilename = null, $mime_type = null ) {
+                $saved = $this->_save( $this->image, $destfilename, $mime_type );
+
+                if ( ! is_wp_error( $saved ) ) {
+                        $this->file = $saved['path'];
+                        $this->mime_type = $saved['mime-type'];
+
+                        try {
+                                $this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) );
+                        }
+                        catch ( Exception $e ) {
+                                return new WP_Error( 'image_save_error', $e->getMessage(), $this->file );
+                        }
+                }
+
+                return $saved;
+        }
+
+        protected function _save( $image, $filename = null, $mime_type = null ) {
+                list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
+
+                if ( ! $filename )
+                        $filename = $this->generate_filename( null, null, $extension );
+
+                try {
+                        // Store initial Format
+                        $orig_format = $this->image->getImageFormat();
+
+                        $this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
+                        $this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
+
+                        // Reset original Format
+                        $this->image->setImageFormat( $orig_format );
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
+                }
+
+                // Set correct file permissions
+                $stat = stat( dirname( $filename ) );
+                $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
+                @ chmod( $filename, $perms );
+
+                return array(
+                        'path' => $filename,
+                        'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
+                        'width' => $this->size['width'],
+                        'height' => $this->size['height'],
+                        'mime-type' => $mime_type,
+                );
+        }
+
+        /**
+         * Streams current image to browser
+         *
+         * @param string $mime_type
+         * @return boolean|WP_Error
+         */
+        public function stream( $mime_type = null ) {
+                list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
+
+                try {
+                        // Temporarily change format for stream
+                        $this->image->setImageFormat( strtoupper( $extension ) );
+
+                        // Output stream of image content
+                        header( "Content-Type: $mime_type" );
+                        print $this->image->getImageBlob();
+
+                        // Reset Image to original Format
+                        $this->image->setImageFormat( $this->get_extension( $this->mime_type ) );
+                }
+                catch ( Exception $e ) {
+                        return new WP_Error( 'image_stream_error', $e->getMessage() );
+                }
+
+                return true;
+        }
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/wp-includes/class-wp-image-editor-imagick.php
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkwpincludesclasswpimageeditorphp"></a>
<div class="addfile"><h4>Added: trunk/wp-includes/class-wp-image-editor.php (0 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-image-editor.php         (rev 0)
+++ trunk/wp-includes/class-wp-image-editor.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -0,0 +1,324 @@
</span><ins>+<?php
+/**
+ * Base WordPress Image Editor
+ *
+ * @package WordPress
+ * @subpackage Image_Editor
+ */
+
+/**
+ * Base WordPress Image Editor class for which Editor implementations extend
+ *
+ * @since 3.5.0
+ */
+abstract class WP_Image_Editor {
+        protected $file = null;
+        protected $size = null;
+        protected $mime_type = null;
+        protected $default_mime_type = 'image/jpeg';
+        protected $quality = 90;
+        private static $implementation;
+
+        protected function __construct( $filename ) {
+                $this->file = $filename;
+        }
+
+        /**
+         * Returns a WP_Image_Editor instance and loads file into it.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param string $path Path to File to Load
+         * @return WP_Image_Editor|WP_Error|boolean
+         */
+        public final static function get_instance( $path = null ) {
+                $implementation = apply_filters( 'image_editor_class', self::choose_implementation(), $path );
+
+                if ( $implementation ) {
+                        $editor = new $implementation( $path );
+                        $loaded = $editor->load();
+
+                        if ( is_wp_error ( $loaded ) )
+                                return $loaded;
+
+                        return $editor;
+                }
+
+                return false;
+        }
+
+        /**
+         * Tests which editors are capable of supporting the request.
+         *
+         * @since 3.5.0
+         * @access private
+         *
+         * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request.
+         */
+        private final static function choose_implementation() {
+
+                if ( null === self::$implementation ) {
+                        $request_order = apply_filters( 'wp_editors', array( 'imagick', 'gd' ) );
+
+                        // Loop over each editor on each request looking for one which will serve this request's needs
+                        foreach ( $request_order as $editor ) {
+                                $class = 'WP_Image_Editor_' . $editor;
+
+                                // Check to see if this editor is a possibility, calls the editor statically
+                                if ( ! call_user_func( array( $class, 'test' ) ) )
+                                        continue;
+
+                                self::$implementation = $class;
+                                break;
+                        }
+                }
+                return self::$implementation;
+        }
+
+        abstract public static function test(); // returns bool
+        abstract protected function load(); // returns bool|WP_Error
+        abstract public static function supports_mime_type( $mime_type ); // returns bool
+        abstract public function resize( $max_w, $max_h, $crop = false );
+        abstract public function multi_resize( $sizes );
+        abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
+        abstract public function rotate( $angle );
+        abstract public function flip( $horz, $vert );
+        abstract public function save( $destfilename = null, $mime_type = null );
+        abstract public function stream( $mime_type = null );
+
+        /**
+         * Gets dimensions of image
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @return array {'width'=>int, 'height'=>int}
+         */
+        public function get_size() {
+                return $this->size;
+        }
+
+        /**
+         * Sets current image size
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param int $width
+         * @param int $height
+         */
+        protected function update_size( $width = null, $height = null ) {
+                $this->size = array(
+                        'width' => $width,
+                        'height' => $height
+                );
+                return true;
+        }
+
+        /**
+         * Sets Image Compression quality on a 1-100% scale.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param int $quality Compression Quality. Range: [1,100]
+         * @return boolean
+         */
+        public function set_quality( $quality ) {
+                $this->quality = apply_filters( 'wp_editor_set_quality', $quality );
+
+                return ( (bool) $this->quality );
+        }
+
+        /**
+         * Returns preferred mime-type and extension based on provided
+         * file's extension and mime, or current file's extension and mime.
+         *
+         * Will default to $this->default_mime_type if requested is not supported.
+         *
+         * Provides corrected filename only if filename is provided.
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param string $filename
+         * @param type $mime_type
+         * @return array { filename|null, extension, mime-type }
+         */
+        protected function get_output_format( $filename = null, $mime_type = null ) {
+                $new_ext = $file_ext = null;
+                $file_mime = null;
+
+                // By default, assume specified type takes priority
+                if ( $mime_type ) {
+                        $new_ext = $this->get_extension( $mime_type );
+                }
+
+                if ( $filename ) {
+                        $file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
+                        $file_mime = $this->get_mime_type( $file_ext );
+                }
+                else {
+                        // If no file specified, grab editor's current extension and mime-type.
+                        $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
+                        $file_mime = $this->mime_type;
+                }
+
+                // Check to see if specified mime-type is the same as type implied by
+                // file extension. If so, prefer extension from file.
+                if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
+                        $mime_type = $file_mime;
+                        $new_ext = $file_ext;
+                }
+
+                // Double-check that the mime-type selected is supported by the editor.
+                // If not, choose a default instead.
+                if ( ! $this->supports_mime_type( $mime_type ) ) {
+                        $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type );
+                        $new_ext = $this->get_extension( $mime_type );
+                }
+
+                if ( $filename ) {
+                        $ext = '';
+                        $info = pathinfo( $filename );
+                        $dir = $info['dirname'];
+
+                        if( isset( $info['extension'] ) )
+                                $ext = $info['extension'];
+
+                        $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}";
+                }
+
+                return array( $filename, $new_ext, $mime_type );
+        }
+
+        /**
+         * Builds an output filename based on current file, and adding proper suffix
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @param string $suffix
+         * @param string $dest_path
+         * @param string $extension
+         * @return string filename
+         */
+        public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
+                // $suffix will be appended to the destination filename, just before the extension
+                if ( ! $suffix )
+                        $suffix = $this->get_suffix();
+
+                $info = pathinfo( $this->file );
+                $dir = $info['dirname'];
+                $ext = $info['extension'];
+
+                $name = wp_basename( $this->file, ".$ext" );
+                $new_ext = strtolower( $extension ? $extension : $ext );
+
+                if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
+                        $dir = $_dest_path;
+
+                return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
+        }
+
+        /**
+         * Builds and returns proper suffix for file based on height and width.
+         *
+         * @since 3.5.0
+         * @access public
+         *
+         * @return string suffix
+         */
+        public function get_suffix() {
+                if ( ! $this->get_size() )
+                        return false;
+
+                return "{$this->size['width']}x{$this->size['height']}";
+        }
+
+        /**
+         * Either calls editor's save function or handles file as a stream.
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param string|stream $filename
+         * @param callable $function
+         * @param array $arguments
+         * @return boolean
+         */
+        protected function make_image( $filename, $function, $arguments ) {
+                $dst_file = $filename;
+
+                if ( $stream = wp_is_stream( $filename ) ) {
+                        $filename = null;
+                        ob_start();
+                }
+
+                $result = call_user_func_array( $function, $arguments );
+
+                if( $result && $stream ) {
+                        $contents = ob_get_contents();
+
+                        $fp = fopen( $dst_file, 'w' );
+
+                        if( ! $fp )
+                                return false;
+
+                        fwrite( $fp, $contents );
+                        fclose( $fp );
+                }
+
+                if( $stream ) {
+                        ob_end_clean();
+                }
+
+                return $result;
+        }
+
+        /**
+         * Returns first matched mime-type from extension,
+         * as mapped from wp_get_mime_types()
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param string $extension
+         * @return string|boolean
+         */
+        protected static function get_mime_type( $extension = null ) {
+                if ( ! $extension )
+                        return false;
+
+                $mime_types = wp_get_mime_types();
+                $extensions = array_keys( $mime_types );
+
+                foreach( $extensions as $_extension ) {
+                        if( preg_match("/{$extension}/i", $_extension ) ) {
+                                return $mime_types[ $_extension ];
+                        }
+                }
+
+                return false;
+        }
+
+        /**
+         * Returns first matched extension from Mime-type,
+         * as mapped from wp_get_mime_types()
+         *
+         * @since 3.5.0
+         * @access protected
+         *
+         * @param string $mime_type
+         * @return string|boolean
+         */
+        protected static function get_extension( $mime_type = null ) {
+                $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) );
+
+                if ( empty( $extensions[0] ) )
+                        return false;
+
+                return $extensions[0];
+        }
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/wp-includes/class-wp-image-editor.php
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkwpincludesdeprecatedphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/deprecated.php (22093 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/deprecated.php        2012-10-01 19:51:23 UTC (rev 22093)
+++ trunk/wp-includes/deprecated.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -3206,6 +3206,83 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><ins>+ * Load an image from a string, if PHP supports it.
+ *
+ * @since 2.1.0
+ * @deprecated 3.5.0
+ * @see WP_Image_Editor
+ *
+ * @param string $file Filename of the image to load.
+ * @return resource The resulting image resource on success, Error string on failure.
+ */
+function wp_load_image( $file ) {
+        _deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor' );
+
+        if ( is_numeric( $file ) )
+                $file = get_attached_file( $file );
+
+        if ( ! file_exists( $file ) )
+                return sprintf(__('File &#8220;%s&#8221; doesn&#8217;t exist?'), $file);
+
+        if ( ! function_exists('imagecreatefromstring') )
+                return __('The GD image library is not installed.');
+
+        // Set artificially high because GD uses uncompressed images in memory
+        @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
+        $image = imagecreatefromstring( file_get_contents( $file ) );
+
+        if ( !is_resource( $image ) )
+                return sprintf(__('File &#8220;%s&#8221; is not an image.'), $file);
+
+        return $image;
+}
+
+/**
+ * Scale down an image to fit a particular size and save a new copy of the image.
+ *
+ * The PNG transparency will be preserved using the function, as well as the
+ * image type. If the file going in is PNG, then the resized image is going to
+ * be PNG. The only supported image types are PNG, GIF, and JPEG.
+ *
+ * Some functionality requires API to exist, so some PHP version may lose out
+ * support. This is not the fault of WordPress (where functionality is
+ * downgraded, not actual defects), but of your PHP version.
+ *
+ * @since 2.5.0
+ * @deprecated 3.5.0
+ * @see WP_Image_Editor
+ *
+ * @param string $file Image file path.
+ * @param int $max_w Maximum width to resize to.
+ * @param int $max_h Maximum height to resize to.
+ * @param bool $crop Optional. Whether to crop image or resize.
+ * @param string $suffix Optional. File suffix.
+ * @param string $dest_path Optional. New image file path.
+ * @param int $jpeg_quality Optional, default is 90. Image quality percentage.
+ * @return mixed WP_Error on failure. String with new destination path.
+ */
+function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
+        _deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor' );
+
+        $editor = WP_Image_Editor::get_instance( $file );
+        if ( is_wp_error( $editor ) )
+                return $editor;
+        $editor->set_quality( $jpeg_quality );
+
+        $resized = $editor->resize( $max_w, $max_h, $crop );
+        if ( is_wp_error( $resized ) )
+                return $resized;
+
+        $dest_file = $editor->generate_filename( $suffix, $dest_path );
+        $saved = $editor->save( $dest_file );
+
+        if ( is_wp_error( $saved ) )
+                return $saved;
+
+        return $dest_file;
+}
+
+/**
</ins><span class="cx"> * Retrieve a single post, based on post ID.
</span><span class="cx"> *
</span><span class="cx"> * Has categories in 'post_category' property or key. Has tags in 'tags_input'
</span></span></pre></div>
<a id="trunkwpincludesfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/functions.php (22093 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/functions.php        2012-10-01 19:51:23 UTC (rev 22093)
+++ trunk/wp-includes/functions.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -1295,9 +1295,21 @@
</span><span class="cx"> * @return bool Whether the path was created. True if path already exists.
</span><span class="cx"> */
</span><span class="cx"> function wp_mkdir_p( $target ) {
</span><ins>+        $wrapper = null;
+
+        // strip the protocol
+        if( wp_is_stream( $target ) ) {
+                list( $wrapper, $target ) = explode( '://', $target, 2 );
+        }
+
</ins><span class="cx">         // from php.net/mkdir user contributed notes
</span><span class="cx">         $target = str_replace( '//', '/', $target );
</span><span class="cx">
</span><ins>+        // put the wrapper back on the target
+        if( $wrapper !== null ) {
+                $target = $wrapper . '://' . $target;
+        }
+
</ins><span class="cx">         // safe mode fails with a trailing slash under certain PHP versions.
</span><span class="cx">         $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
</span><span class="cx">         if ( empty($target) )
</span><span class="lines">@@ -3750,6 +3762,19 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><ins>+ * Test if a given path is a stream URL
+ *
+ * @param string $path The resource path or URL
+ * @return bool True if the path is a stream URL
+ */
+function wp_is_stream( $path ) {
+        $wrappers = stream_get_wrappers();
+        $wrappers_re = '(' . join('|', $wrappers) . ')';
+
+        return preg_match( "!^$wrappers_re://!", $path ) === 1;
+}
+
+/**
</ins><span class="cx"> * Test if the supplied date is valid for the Gregorian calendar
</span><span class="cx"> *
</span><span class="cx"> * @since 3.5.0
</span></span></pre></div>
<a id="trunkwpincludesmediaphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/media.php (22093 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/media.php        2012-10-01 19:51:23 UTC (rev 22093)
+++ trunk/wp-includes/media.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -236,34 +236,6 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * Load an image from a string, if PHP supports it.
- *
- * @since 2.1.0
- *
- * @param string $file Filename of the image to load.
- * @return resource The resulting image resource on success, Error string on failure.
- */
-function wp_load_image( $file ) {
-        if ( is_numeric( $file ) )
-                $file = get_attached_file( $file );
-
-        if ( ! file_exists( $file ) )
-                return sprintf(__('File &#8220;%s&#8221; doesn&#8217;t exist?'), $file);
-
-        if ( ! function_exists('imagecreatefromstring') )
-                return __('The GD image library is not installed.');
-
-        // Set artificially high because GD uses uncompressed images in memory
-        @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
-        $image = imagecreatefromstring( file_get_contents( $file ) );
-
-        if ( !is_resource( $image ) )
-                return sprintf(__('File &#8220;%s&#8221; is not an image.'), $file);
-
-        return $image;
-}
-
-/**
</del><span class="cx"> * Calculates the new dimensions for a downsampled image.
</span><span class="cx"> *
</span><span class="cx"> * If either width or height are empty, no constraint is applied on
</span><span class="lines">@@ -393,92 +365,6 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * Scale down an image to fit a particular size and save a new copy of the image.
- *
- * The PNG transparency will be preserved using the function, as well as the
- * image type. If the file going in is PNG, then the resized image is going to
- * be PNG. The only supported image types are PNG, GIF, and JPEG.
- *
- * Some functionality requires API to exist, so some PHP version may lose out
- * support. This is not the fault of WordPress (where functionality is
- * downgraded, not actual defects), but of your PHP version.
- *
- * @since 2.5.0
- *
- * @param string $file Image file path.
- * @param int $max_w Maximum width to resize to.
- * @param int $max_h Maximum height to resize to.
- * @param bool $crop Optional. Whether to crop image or resize.
- * @param string $suffix Optional. File suffix.
- * @param string $dest_path Optional. New image file path.
- * @param int $jpeg_quality Optional, default is 90. Image quality percentage.
- * @return mixed WP_Error on failure. String with new destination path.
- */
-function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
-
-        $image = wp_load_image( $file );
-        if ( !is_resource( $image ) )
-                return new WP_Error( 'error_loading_image', $image, $file );
-
-        $size = @getimagesize( $file );
-        if ( !$size )
-                return new WP_Error('invalid_image', __('Could not read image size'), $file);
-        list($orig_w, $orig_h, $orig_type) = $size;
-
-        $dims = image_resize_dimensions($orig_w, $orig_h, $max_w, $max_h, $crop);
-        if ( !$dims )
-                return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
-        list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;
-
-        $newimage = wp_imagecreatetruecolor( $dst_w, $dst_h );
-
-        imagecopyresampled( $newimage, $image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
-
-        // convert from full colors to index colors, like original PNG.
-        if ( IMAGETYPE_PNG == $orig_type && function_exists('imageistruecolor') && !imageistruecolor( $image ) )
-                imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) );
-
-        // we don't need the original in memory anymore
-        imagedestroy( $image );
-
-        // $suffix will be appended to the destination filename, just before the extension
-        if ( !$suffix )
-                $suffix = "{$dst_w}x{$dst_h}";
-
-        $info = pathinfo($file);
-        $dir = $info['dirname'];
-        $ext = $info['extension'];
-        $name = wp_basename($file, ".$ext");
-
-        if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) )
-                $dir = $_dest_path;
-        $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
-
-        if ( IMAGETYPE_GIF == $orig_type ) {
-                if ( !imagegif( $newimage, $destfilename ) )
-                        return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
-        } elseif ( IMAGETYPE_PNG == $orig_type ) {
-                if ( !imagepng( $newimage, $destfilename ) )
-                        return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
-        } else {
-                // all other formats are converted to jpg
-                if ( 'jpg' != $ext && 'jpeg' != $ext )
-                        $destfilename = "{$dir}/{$name}-{$suffix}.jpg";
-                if ( !imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality, 'image_resize' ) ) )
-                        return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
-        }
-
-        imagedestroy( $newimage );
-
-        // Set correct file permissions
-        $stat = stat( dirname( $destfilename ));
-        $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
-        @ chmod( $destfilename, $perms );
-
-        return $destfilename;
-}
-
-/**
</del><span class="cx"> * Resize an image to make a thumbnail or intermediate size.
</span><span class="cx"> *
</span><span class="cx"> * The returned array has the file size, the image width, and image height. The
</span><span class="lines">@@ -493,16 +379,18 @@
</span><span class="cx"> * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
</span><span class="cx"> * @return bool|array False, if no image was created. Metadata array on success.
</span><span class="cx"> */
</span><del>-function image_make_intermediate_size($file, $width, $height, $crop=false) {
</del><ins>+function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
</ins><span class="cx">         if ( $width || $height ) {
</span><del>-                $resized_file = image_resize($file, $width, $height, $crop);
-                if ( !is_wp_error($resized_file) && $resized_file && $info = getimagesize($resized_file) ) {
-                        $resized_file = apply_filters('image_make_intermediate_size', $resized_file);
-                        return array(
-                                'file' => wp_basename( $resized_file ),
-                                'width' => $info[0],
-                                'height' => $info[1],
-                        );
</del><ins>+                $editor = WP_Image_Editor::get_instance( $file );
+
+                if ( is_wp_error( $editor->resize( $width, $height, $crop ) ) );
+                        return false;
+
+                $resized_file = $editor->save();
+
+                if ( ! is_wp_error( $resized_file ) && $resized_file ) {
+                        unset( $resized_file['path'] );
+                        return $resized_file;
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return false;
</span><span class="lines">@@ -1047,6 +935,7 @@
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Create new GD image resource with transparency support
</span><ins>+ * @TODO: Deprecate if possible.
</ins><span class="cx"> *
</span><span class="cx"> * @since 2.9.0
</span><span class="cx"> *
</span></span></pre></div>
<a id="trunkwpsettingsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-settings.php (22093 => 22094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-settings.php        2012-10-01 19:51:23 UTC (rev 22093)
+++ trunk/wp-settings.php        2012-10-01 20:59:06 UTC (rev 22094)
</span><span class="lines">@@ -143,6 +143,10 @@
</span><span class="cx"> require( ABSPATH . WPINC . '/nav-menu-template.php' );
</span><span class="cx"> require( ABSPATH . WPINC . '/admin-bar.php' );
</span><span class="cx">
</span><ins>+require( ABSPATH . WPINC . '/class-wp-image-editor.php' );
+require( ABSPATH . WPINC . '/class-wp-image-editor-gd.php' );
+require( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' );
+
</ins><span class="cx"> // Load multisite-specific files.
</span><span class="cx"> if ( is_multisite() ) {
</span><span class="cx">         require( ABSPATH . WPINC . '/ms-functions.php' );
</span></span></pre>
</div>
</div>
</body>
</html>