diff --git wp-admin/includes/image-edit.php wp-admin/includes/image-edit.php
index 8185c20..8984767 100644
--- wp-admin/includes/image-edit.php
+++ wp-admin/includes/image-edit.php
@@ -197,39 +197,79 @@ function wp_image_editor($post_id, $msg = false) {
 <?php
 }
 
-function wp_stream_image($image, $mime_type, $post_id) {
-	$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;
+/**
+ * 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);
+		$image->stream();
+
+    } 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;
+		}
 	}
 }
 
-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;
-
-	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;
+/**
+ * @TODO: Public function that accepts GD images as input.
+ * @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);
+
+		if ( null !== $saved )
+			return $saved;
+
+		return $image->save( $filename );
+	} 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;
+		}
 	}
 }
 
@@ -238,7 +278,9 @@ function _image_get_preview_ratio($w, $h) {
 	return $max > 400 ? (400 / $max) : 1;
 }
 
+// @TODO: Returns GD resource, but is NOT public
 function _rotate_image_resource($img, $angle) {
+	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
 	if ( function_exists('imagerotate') ) {
 		$rotated = imagerotate($img, $angle, 0);
 		if ( is_resource($rotated) ) {
@@ -249,7 +291,18 @@ function _rotate_image_resource($img, $angle) {
 	return $img;
 }
 
+/**
+ * @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
+ */
 function _flip_image_resource($img, $horz, $vert) {
+	_deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
 	$w = imagesx($img);
 	$h = imagesy($img);
 	$dst = wp_imagecreatetruecolor($w, $h);
@@ -267,6 +320,18 @@ function _flip_image_resource($img, $horz, $vert) {
 	return $img;
 }
 
+/**
+ * @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
+ */
 function _crop_image_resource($img, $x, $y, $w, $h) {
 	$dst = wp_imagecreatetruecolor($w, $h);
 	if ( is_resource($dst) ) {
@@ -278,10 +343,19 @@ function _crop_image_resource($img, $x, $y, $w, $h) {
 	return $img;
 }
 
-function image_edit_apply_changes($img, $changes) {
+/**
+ * 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' ) );
 
 	if ( !is_array($changes) )
-		return $img;
+		return $image;
 
 	// expand change operations
 	foreach ( $changes as $key => $obj ) {
@@ -326,54 +400,81 @@ function image_edit_apply_changes($img, $changes) {
 	}
 
 	// image resource before applying the changes
-	$img = apply_filters('image_edit_before_change', $img, $changes);
+	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);
 
 	foreach ( $changes as $operation ) {
 		switch ( $operation->type ) {
 			case 'rotate':
-				if ( $operation->angle != 0 )
-					$img = _rotate_image_resource($img, $operation->angle);
+				if ( $operation->angle != 0 ) {
+					if ( $image instanceof WP_Image_Editor )
+						$image->rotate( $operation->angle );
+					else
+						$image = _rotate_image_resource( $image, $operation->angle );
+				}
 				break;
 			case 'flip':
 				if ( $operation->axis != 0 )
-					$img = _flip_image_resource($img, ($operation->axis & 1) != 0, ($operation->axis & 2) != 0);
+					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 );
 				break;
 			case 'crop':
 				$sel = $operation->sel;
-				$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);
+
+				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 );
+				}
 				break;
 		}
 	}
 
-	return $img;
+	return $image;
 }
 
+
+/**
+ * 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);
 	@ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
-	$img = load_image_to_edit( $post_id, $post->post_mime_type, array(400, 400) );
 
-	if ( !is_resource($img) )
-		return false;
+	$img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id ) );
+
+    if ( ! $img )
+        return false;
 
 	$changes = !empty($_REQUEST['history']) ? json_decode( stripslashes($_REQUEST['history']) ) : null;
 	if ( $changes )
-		$img = image_edit_apply_changes($img, $changes);
+		$img = image_edit_apply_changes( $img, $changes );
 
 	// scale the image
-	$w = imagesx($img);
-	$h = imagesy($img);
-	$ratio = _image_get_preview_ratio($w, $h);
+	$size = $img->get_size();
+	$w = $size['width'];
+	$h = $size['height'];
+
+	$ratio = _image_get_preview_ratio( $w, $h );
 	$w2 = $w * $ratio;
 	$h2 = $h * $ratio;
 
-	$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);
-
-	imagedestroy($preview);
-	imagedestroy($img);
+	$img->resize( $w2, $h2 );
+	wp_stream_image( $img, $post->post_mime_type, $post_id );
 	return true;
 }
 
@@ -450,14 +551,20 @@ function wp_restore_image($post_id) {
 	return $msg;
 }
 
-function wp_save_image($post_id) {
+/**
+ * Saves image to post along with enqueued changes
+ * in $_REQUEST['history']
+ *
+ * @param int $post_id
+ * @return \stdClass
+ */
+function wp_save_image( $post_id ) {
 	$return = new stdClass;
 	$success = $delete = $scaled = $nocrop = false;
-	$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);
+	$post = get_post( $post_id );
 
-	if ( !is_resource($img) ) {
+	$img = WP_Image_Editor::get_instance( _load_image_to_edit_path( $post_id, 'full' ) );
+	if ( !$img ) {
 		$return->error = esc_js( __('Unable to create new image.') );
 		return $return;
 	}
@@ -468,19 +575,16 @@ function wp_save_image($post_id) {
 	$scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do'];
 
 	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
-		$sX = imagesx($img);
-		$sY = imagesy($img);
+		$size = $img->get_size();
+		$sX = $size['width'];
+		$sY = $size['height'];
 
 		// check if it has roughly the same w / h ratio
 		$diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
 		if ( -0.1 < $diff && $diff < 0.1 ) {
 			// scale the full size image
-			$dst = wp_imagecreatetruecolor($fwidth, $fheight);
-			if ( imagecopyresampled( $dst, $img, 0, 0, 0, 0, $fwidth, $fheight, $sX, $sY ) ) {
-				imagedestroy($img);
-				$img = $dst;
+			if ( $img->resize( $fwidth, $fheight ) )
 				$scaled = true;
-			}
 		}
 
 		if ( !$scaled ) {
@@ -551,11 +655,13 @@ function wp_save_image($post_id) {
 		if ( $tag )
 			$backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
 
-		$success = update_attached_file($post_id, $new_path);
+		$success = update_attached_file( $post_id, $new_path );
+
+		$meta['file'] = _wp_relative_upload_path( $new_path );
 
-		$meta['file'] = _wp_relative_upload_path($new_path);
-		$meta['width'] = imagesx($img);
-		$meta['height'] = imagesy($img);
+		$size = $img->get_size();
+		$meta['width'] = $size['width'];
+		$meta['height'] = $size['height'];
 
 		if ( $success && ('nothumb' == $target || 'all' == $target) ) {
 			$sizes = get_intermediate_image_sizes();
@@ -570,10 +676,12 @@ function wp_save_image($post_id) {
 		$success = $delete = $nocrop = true;
 	}
 
-	if ( isset($sizes) ) {
+	if ( isset( $sizes ) ) {
+		$_sizes = array();
+
 		foreach ( $sizes as $size ) {
 			$tag = false;
-			if ( isset($meta['sizes'][$size]) ) {
+			if ( isset( $meta['sizes'][$size] ) ) {
 				if ( isset($backup_sizes["$size-orig"]) ) {
 					if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] )
 						$tag = "$size-$suffix";
@@ -586,17 +694,16 @@ function wp_save_image($post_id) {
 			}
 
 			$crop = $nocrop ? false : get_option("{$size}_crop");
-			$resized = image_make_intermediate_size($new_path, get_option("{$size}_size_w"), get_option("{$size}_size_h"), $crop );
-
-			if ( $resized )
-				$meta['sizes'][$size] = $resized;
-			else
-				unset($meta['sizes'][$size]);
+			$_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop );
 		}
+
+		$meta['sizes'] = $img->multi_resize( $_sizes );
 	}
 
+	unset( $img );
+
 	if ( $success ) {
-		wp_update_attachment_metadata($post_id, $meta);
+		wp_update_attachment_metadata( $post_id, $meta );
 		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes);
 
 		if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) {
@@ -612,11 +719,9 @@ function wp_save_image($post_id) {
 
 	if ( $delete ) {
 		$delpath = apply_filters('wp_delete_file', $new_path);
-		@unlink($delpath);
+		@unlink( $delpath );
 	}
 
-	imagedestroy($img);
-
 	$return->msg = esc_js( __('Image saved') );
 	return $return;
 }
diff --git wp-admin/includes/image.php wp-admin/includes/image.php
index 2de1a7e..fab8a5a 100644
--- wp-admin/includes/image.php
+++ wp-admin/includes/image.php
@@ -43,61 +43,33 @@ function wp_create_thumbnail( $file, $max_side, $deprecated = '' ) {
  * @param string $dst_file Optional. The destination file to write to.
  * @return string|WP_Error|false New filepath on success, WP_Error or false on failure.
  */
-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 );
+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 );
 		if ( ! file_exists( $src_file ) ) {
 			// If the file doesn't exist, attempt a url fopen on the src link.
 			// This can occur with certain file replication plugins.
-			$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 );
+			$src_file = _load_image_to_edit_path( $src_file, 'full' );
 		}
-	} else {
-		$size = @getimagesize( $src );
-		$image_type = ( $size ) ? $size['mime'] : '';
-		$src = wp_load_image( $src );
-	}
-
-	if ( ! is_resource( $src ) )
-		return new WP_Error( 'error_loading_image', $src, $src_file );
-
-	$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, $src, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h );
+	$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 );
 
-	imagedestroy( $src ); // Free up memory
+	if ( ! $src )
+		return new WP_Error( 'error_loading_image', '', $src_file );
 
 	if ( ! $dst_file )
 		$dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file );
 
-	if ( 'image/png' != $image_type )
-		$dst_file = preg_replace( '/\\.[^\\.]+$/', '.jpg', $dst_file );
-
 	// The directory containing the original file may no longer exist when
 	// using a replication plugin.
 	wp_mkdir_p( dirname( $dst_file ) );
 
 	$dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) );
 
-	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;
+	$result = $editor->save( $dst_file );
+	return $dst_file;
 }
 
 /**
@@ -142,11 +114,8 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
 
 		$sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes );
 
-		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;
-		}
+		$editor = WP_Image_Editor::get_instance( $file );
+		$metadata['sizes'] = $editor->multi_resize( $sizes );
 
 		// fetch additional metadata from exif/iptc
 		$image_meta = wp_read_image_metadata( $file );
diff --git wp-includes/class-wp-image-editor-gd.php wp-includes/class-wp-image-editor-gd.php
new file mode 100644
index 0000000..1845172
--- /dev/null
+++ wp-includes/class-wp-image-editor-gd.php
@@ -0,0 +1,284 @@
+<?php
+
+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 GD is available.
+	 *
+	 * @since 3.5
+	 *
+	 * @return boolean
+	 */
+	public static function test() {
+		if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
+			return false;
+
+		return true;
+	}
+
+	/**
+	 * Loads image from $this->file into GD Resource
+	 *
+	 * @since 3.5
+	 *
+	 * @return boolean|\WP_Error
+	 */
+	protected function load() {
+		if ( $this->image )
+			return true;
+
+		if ( ! file_exists( $this->file ) )
+			return sprintf( __('File &#8220;%s&#8221; doesn&#8217;t exist?'), $this->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 ) );
+		$this->image = imagecreatefromstring( file_get_contents( $this->file ) );
+
+		if ( ! is_resource( $this->image ) )
+			return sprintf( __('File &#8220;%s&#8221; 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->orig_type = $size['mime'];
+
+		return true;
+	}
+
+	protected function update_size( $width = false, $height = false ) {
+		parent::update_size( $width ?: imagesx( $this->image ), $height ?: imagesy( $this->image ) );
+	}
+
+	/**
+	 * Resizes Image.
+	 * Wrapper around _resize, since _resize returns a GD Resource
+	 *
+	 * @param int $max_w
+	 * @param int $max_h
+	 * @param boolean $crop
+	 * @return boolean
+	 */
+	public function resize( $max_w, $max_h, $crop = false ) {
+		$resized = $this->_resize( $max_w, $max_h, $crop );
+
+		if ( is_resource( $resized ) ) {
+			imagedestroy( $this->image );
+			$this->image = $resized;
+
+			return true;
+		}
+
+		return false;
+	}
+
+	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') );
+		}
+		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 false;
+	}
+
+	/**
+	 * 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;
+		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;
+	}
+
+	/**
+	 * Ported from image.php
+	 *
+	 * @param float $x
+	 * @param float $y
+	 * @param float $w
+	 * @param float $h
+	 * @return boolean
+	 */
+	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.
+		$dst_w = $dst_w ?: $src_w;
+		$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 false; // @TODO: WP_Error here.
+	}
+
+	/**
+	 * Rotates in memory image by $angle.
+	 * Ported from image-edit.php
+	 *
+	 * @param float $angle
+	 * @return boolean
+	 */
+	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 false; // @TODO: WP_Error here.
+	}
+
+	/**
+	 * Ported from image-edit.php
+	 *
+	 * @param boolean $horz
+	 * @param boolean $vert
+	 */
+	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 false; // @TODO: WP_Error here.
+	}
+
+	/**
+	 * Saves current in-memory image to file
+	 *
+	 * @param string $destfilename
+	 * @return array
+	 */
+	public function save( $destfilename = null ) {
+		$saved = $this->_save( $this->image, $destfilename );
+
+		if ( ! is_wp_error( $saved ) && $destfilename )
+			$this->file = $destfilename;
+
+		return $saved;
+	}
+
+	protected function _save( $image, $destfilename = null ) {
+		if ( null == $destfilename ) {
+			$destfilename = $this->generate_filename();
+		}
+
+		if ( 'image/gif' == $this->orig_type ) {
+			if ( ! $this->make_image( $destfilename, 'imagegif', array( $image, $destfilename ) ) )
+				return new WP_Error( 'image_editor_save_failed', __( 'Image Editor Save Failed' ) );
+		}
+		elseif ( 'image/png' == $this->orig_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( $destfilename, 'imagepng', array( $image, $destfilename ) ) )
+				return new WP_Error( 'image_editor_save_failed', __( 'Image Editor Save Failed' ) );
+		}
+		else {
+			if ( ! $this->make_image( $destfilename, 'imagejpeg', array( $image, $destfilename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) )
+				return new WP_Error( 'image_editor_save_failed', __( 'Image Editor Save Failed' ) );
+		}
+
+		// 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 array(
+			'path' => $destfilename,
+			'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $destfilename ) ),
+			'width' => $this->size['width'],
+			'height' => $this->size['height']
+		);
+	}
+
+	/**
+	 * Returns stream of current image
+	 */
+	public function stream() {
+		switch ( $this->orig_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 );
+		}
+	}
+}
\ No newline at end of file
diff --git wp-includes/class-wp-image-editor-imagick.php wp-includes/class-wp-image-editor-imagick.php
new file mode 100644
index 0000000..6045bed
--- /dev/null
+++ wp-includes/class-wp-image-editor-imagick.php
@@ -0,0 +1,270 @@
+<?php
+
+class WP_Image_Editor_Imagick extends WP_Image_Editor {
+	private $image = null; // Imagick Object
+
+	function __destruct() {
+		if ( $this->image ) {
+			// we don't need the original in memory anymore
+			$this->image->destroy();
+		}
+	}
+
+	public static function test() {
+		if ( ! extension_loaded('imagick') )
+			return false;
+
+		return true;
+	}
+
+	protected function load() {
+		if ( $this->image )
+			return true;
+
+		if ( ! file_exists( $this->file ) )
+			return sprintf( __('File &#8220;%s&#8221; doesn&#8217;t exist?'), $this->file );
+
+		try {
+			$this->image = new Imagick( $this->file );
+			$this->image->setIteratorIndex(0);
+		}
+		catch ( Exception $e ) {
+			return sprintf(__('File &#8220;%s&#8221; is not an image.'), $this->file);
+		}
+
+		if( ! $this->image->valid() ) {
+			return sprintf(__('File &#8220;%s&#8221; is not an image.'), $this->file);
+		}
+
+		$this->update_size();
+		$this->orig_type  = $this->image->getImageFormat(); // TODO: Wrap in exception handling
+		if ( ! $this->size )
+			return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file );
+
+		$this->set_quality();
+
+		return true;
+	}
+
+	public function set_quality( $quality = null ) {
+		$quality = $quality ?: $this->quality;
+
+		if( 'JPEG' == $this->orig_type ) {
+			$this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) );
+			$this->image->setImageCompression( imagick::COMPRESSION_JPEG );
+		}
+		else {
+			$this->image->setImageCompressionQuality( $quality );
+		}
+
+		return parent::set_quality( $quality );
+	}
+
+	protected function update_size( $width = null, $height = null ) {
+		$size = null;
+		if ( !$width || !$height ) {
+			try {
+				$size = $this->image->getImageGeometry();
+			}
+			catch ( Exception $e ) {
+				return sprintf(__('File &#8220;%s&#8221; couldn\'t be checked for size.'), $this->file);
+			}
+		}
+
+		parent::update_size( $width ?: $size['width'], $height ?: $size['height'] );
+	}
+
+	public 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') );
+		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 );
+		}
+
+		//$this->image->thumbnailImage( $dst_w, $dst_h );
+		$this->image->scaleImage( $dst_w, $dst_h );
+		$this->update_size( $dst_w, $dst_h );
+
+		return true;
+	}
+
+	/**
+	 * 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->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.
+	 *
+	 * @param float $x
+	 * @param float $y
+	 * @param float $w
+	 * @param float $h
+	 * @return boolean
+	 */
+	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;
+		}
+
+		$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.
+			$dst_w = $dst_w ?: $src_w;
+			$dst_h = $dst_h ?: $src_h;
+
+			$this->image->scaleImage( $dst_w, $dst_h );
+			$this->update_size( $dst_w, $dst_h );
+			return true;
+		}
+
+		$this->update_size( $src_w, $src_h );
+		return true;
+
+		// @TODO: We need exception handling above  // return false;
+	}
+
+	/**
+	 * Rotates in memory image by $angle.
+	 * Ported from image-edit.php
+	 *
+	 * @param float $angle
+	 * @return boolean
+	 */
+	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 );
+			$this->update_size();
+		}
+		catch ( Exception $e ) {
+			return false; // TODO: WP_Error Here.
+		}
+	}
+
+	/**
+	 * Flips Image
+	 *
+	 * @param boolean $horz
+	 * @param boolean $vert
+	 * @returns boolean
+	 */
+	public function flip( $horz, $vert ) {
+		try {
+			if ( $horz )
+				$this->image->flipImage();
+
+			if ( $vert )
+				$this->image->flopImage();
+		}
+		catch ( Exception $e ) {
+			return false; // TODO: WP_Error Here.
+		}
+
+		return true;
+	}
+
+	/**
+	 * Saves current image to file
+	 *
+	 * @param string $destfilename
+	 * @return array
+	 */
+	public function save( $destfilename = null ) {
+		$saved = $this->_save( $this->image, $destfilename );
+
+		if ( ! is_wp_error( $saved ) && $destfilename )
+			$this->file = $destfilename;
+
+		return $saved;
+	}
+
+	protected function _save( $image, $destfilename = null ) {
+		if ( null == $destfilename ) {
+			$destfilename = $this->generate_filename();
+		}
+
+		if( apply_filters( 'wp_editors_stripimage', true ) ) {
+			$image->stripImage();
+		}
+
+		$this->make_image( $destfilename, array( $image, 'writeImage' ), array( $destfilename ) );
+
+		// 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 array(
+			'path' => $destfilename,
+			'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $destfilename ) ),
+			'width' => $this->size['width'],
+			'height' => $this->size['height']
+		);
+	}
+
+	/**
+	 * @TODO: Wrap in try and clean up.
+	 * Also, make GIF not stream the last frame :(
+	 *
+	 * @return boolean
+	 */
+	public function stream() {
+		switch ( $this->orig_type ) {
+			case 'PNG':
+				header( 'Content-Type: image/png' );
+				break;
+			case 'GIF':
+				header( 'Content-Type: image/gif' );
+				break;
+			default:
+				header( 'Content-Type: image/jpeg' );
+				break;
+		}
+
+		print $this->image->getImageBlob();
+		return true;
+	}
+}
\ No newline at end of file
diff --git wp-includes/class-wp-image-editor.php wp-includes/class-wp-image-editor.php
new file mode 100644
index 0000000..972aa5f
--- /dev/null
+++ wp-includes/class-wp-image-editor.php
@@ -0,0 +1,136 @@
+<?php
+
+abstract class WP_Image_Editor {
+	protected $file = null;
+	protected $size = null;
+	protected $orig_type  = null;
+	protected $quality = 90;
+
+	protected function __construct( $filename ) {
+		$this->file = $filename;
+
+		return $this->load();
+	}
+
+	public final static function get_instance( $path ) {
+		$implementation = apply_filters( 'image_editor_class', self::choose_implementation(), $path );
+
+		if ( $implementation )
+			return new $implementation( $path );
+
+		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() {
+		static $implementation;
+
+		if ( null === $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;
+
+				$implementation = $class;
+
+				break;
+			}
+		}
+
+		return $implementation;
+	}
+
+	abstract public static function test();
+	abstract protected function load();
+	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 );
+	abstract public function stream();
+
+	public function get_size() {
+		return $this->size;
+	}
+
+	protected function update_size( $width = null, $height = null ) {
+		$this->size = array(
+			'width' => $width,
+			'height' => $height
+		);
+	}
+
+	public function set_quality( $quality ) {
+		$this->quality = apply_filters( 'wp_editor_set_quality', $quality );
+	}
+
+	public function generate_filename( $suffix = null, $dest_path = null ) {
+		// $suffix will be appended to the destination filename, just before the extension
+		$suffix = $this->get_suffix();
+
+		$info = pathinfo( $this->file );
+		$dir  = $info['dirname'];
+		$ext  = $info['extension'];
+
+		// Convert any unrecognized formats to jpeg
+		if ( !in_array( strtolower( $ext ), array( 'png', 'jpg', 'jpeg', 'gif' ) ) ) {
+			$ext = 'jpg';
+		}
+
+		$name = wp_basename( $this->file, ".$ext" );
+
+		if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
+			$dir = $_dest_path;
+
+		return "{$dir}/{$name}-{$suffix}.{$ext}";
+	}
+
+	public function get_suffix() {
+		if ( ! $this->get_size() )
+			return false;
+
+		return "{$this->size['width']}x{$this->size['height']}";
+	}
+
+	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;
+	}
+}
\ No newline at end of file
diff --git wp-includes/deprecated.php wp-includes/deprecated.php
index da8bb1d..74c956f 100644
--- wp-includes/deprecated.php
+++ wp-includes/deprecated.php
@@ -3206,6 +3206,73 @@ function _get_post_ancestors( &$post ) {
 }
 
 /**
+ * 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 );
+	$editor->set_quality( $jpeg_quality );
+
+	$editor->resize( $max_w, $max_h, $crop );
+	$editor->save( $editor->generate_filename( $suffix, $dest_path ) );
+	unset( $editor );
+}
+
+/**
  * Retrieve a single post, based on post ID.
  *
  * Has categories in 'post_category' property or key. Has tags in 'tags_input'
diff --git wp-includes/functions.php wp-includes/functions.php
index b051467..28e2bc8 100644
--- wp-includes/functions.php
+++ wp-includes/functions.php
@@ -1292,9 +1292,21 @@ function wp_get_original_referer() {
  * @return bool Whether the path was created. True if path already exists.
  */
 function wp_mkdir_p( $target ) {
+	$wrapper = null;
+
+	// strip the protocol
+	if( wp_is_stream( $target ) ) {
+		list( $wrapper, $target ) = explode( '://', $target, 2 );
+	}
+
 	// from php.net/mkdir user contributed notes
 	$target = str_replace( '//', '/', $target );
 
+	// put the wrapper back on the target
+	if( $wrapper !== null ) {
+		$target = $wrapper . '://' . $target;
+	}
+
 	// safe mode fails with a trailing slash under certain PHP versions.
 	$target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
 	if ( empty($target) )
@@ -3686,3 +3698,15 @@ function _device_can_upload() {
 	return true;
 }
 
+/**
+ * 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;
+}
diff --git wp-includes/media.php wp-includes/media.php
index fbdd6d2..13325bb 100644
--- wp-includes/media.php
+++ wp-includes/media.php
@@ -236,34 +236,6 @@ function get_image_tag($id, $alt, $title, $align, $size='medium') {
 }
 
 /**
- * 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;
-}
-
-/**
  * Calculates the new dimensions for a downsampled image.
  *
  * If either width or height are empty, no constraint is applied on
@@ -393,92 +365,6 @@ function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = fal
 }
 
 /**
- * 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;
-}
-
-/**
  * Resize an image to make a thumbnail or intermediate size.
  *
  * The returned array has the file size, the image width, and image height. The
@@ -493,16 +379,17 @@ function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $de
  * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
  * @return bool|array False, if no image was created. Metadata array on success.
  */
-function image_make_intermediate_size($file, $width, $height, $crop=false) {
+function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
 	if ( $width || $height ) {
-		$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],
-			);
+		$editor = WP_Image_Editor::get_instance( $file );
+		$editor->resize( $width, $height, $crop );
+		$resized_file = $editor->save();
+
+		unset( $editor );
+
+		if ( ! is_wp_error( $resized_file ) && $resized_file ) {
+			unset( $resized_file['path'] );
+			return $resized_file;
 		}
 	}
 	return false;
@@ -1020,6 +907,7 @@ function gd_edit_image_support($mime_type) {
 
 /**
  * Create new GD image resource with transparency support
+ * @TODO: Deprecate if possible.
  *
  * @since 2.9.0
  *
diff --git wp-settings.php wp-settings.php
index 2db338b..0022613 100644
--- wp-settings.php
+++ wp-settings.php
@@ -142,6 +142,10 @@ require( ABSPATH . WPINC . '/nav-menu.php' );
 require( ABSPATH . WPINC . '/nav-menu-template.php' );
 require( ABSPATH . WPINC . '/admin-bar.php' );
 
+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' );
+
 // Load multisite-specific files.
 if ( is_multisite() ) {
 	require( ABSPATH . WPINC . '/ms-functions.php' );
