Index: src/wp-includes/class-wp-image-editor-gd.php
===================================================================
--- src/wp-includes/class-wp-image-editor-gd.php	(revision 36486)
+++ src/wp-includes/class-wp-image-editor-gd.php	(working copy)
@@ -486,4 +486,37 @@
 
 		return parent::make_image( $filename, $function, $arguments );
 	}
+
+	public function is_animated() {
+		if ( null === $this->animated ) {
+			if ( 'image/jpg' === $this->mime_type ) {
+				$this->animated = false;
+			}
+			else if ( ! ( $fh = @fopen( $this->file, 'rb' ) ) ) {
+				$this->animated = false;
+			}
+			else {
+				$count = 0;
+				//an animated gif contains multiple "frames", with each frame having a
+				//header made up of:
+				// * a static 4-byte sequence (\x00\x21\xF9\x04)
+				// * 4 variable bytes
+				// * a static 2-byte sequence (\x00\x2C)
+
+				// We read through the file til we reach the end of the file, or we've found
+				// at least 2 frame headers
+				while( ! feof($fh) && $count < 2 ) {
+					$chunk  = fread( $fh, 1024 * 100 ); //read 100kb at a time
+					$count += preg_match_all( '#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches );
+				}
+
+				fclose($fh);
+
+				$this->animated = $count > 1;
+			}
+		}
+
+		return $this->animated;
+	}
+
 }
Index: src/wp-includes/class-wp-image-editor-imagick.php
===================================================================
--- src/wp-includes/class-wp-image-editor-imagick.php	(revision 36486)
+++ src/wp-includes/class-wp-image-editor-imagick.php	(working copy)
@@ -139,6 +139,16 @@
 			if ( ! $this->image->valid() )
 				return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file);
 
+			// We need to check to see if image is animated before we set the index, or else it returns false.
+			// For animation to be supported, also getImageBlob, writeImages, coalesceImages and optimizeImageLayers are required.
+			// While coalesceImages seems to be supported far back, optimizeImageLayers is not.
+			if ( method_exists( $this->image, 'coalesceImages' ) ) {
+				$this->animated = (bool) ( count( $this->image->coalesceImages() ) - 1);
+			}
+			else {
+				$this->animated = false;
+			}
+
 			// Select the first frame to handle animated images properly
 			if ( is_callable( array( $this->image, 'setIteratorIndex' ) ) )
 				$this->image->setIteratorIndex(0);
@@ -250,11 +260,22 @@
 		}
 
 		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 );
+			if ( $this->animated ) {
+				$this->image = $this->image->coalesceImages();
+			}
+
+			foreach ($this->image as $frame) {
+				/**
+				 * @TODO: Thumbnail is more efficient, given a newer version of Imagemagick.
+				 * $this->image->thumbnailImage( $dst_w, $dst_h );
+				 */
+				$frame->scaleImage( $dst_w, $dst_h );
+			}
+
+			# $this->deconstructImages(); or $this->optimizeImageLayers();
+			if ( $this->animated ) {
+				$this->image = $this->image->optimizeImageLayers();
+			}
 		}
 		catch ( Exception $e ) {
 			return new WP_Error( 'image_resize_error', $e->getMessage() );
@@ -356,20 +377,29 @@
 		}
 
 		try {
-			$this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
-			$this->image->setImagePage( $src_w, $src_h, 0, 0);
+			if ( $this->animated ) {
+				$this->image = $this->image->coalesceImages();
+			}
 
-			if ( $dst_w || $dst_h ) {
-				// If destination width/height isn't specified, use same as
-				// width/height from source.
-				if ( ! $dst_w )
+			foreach ($this->image as $frame) {
+				$frame->cropImage( $src_w, $src_h, $src_x, $src_y );
+				$frame->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;
+					if ( ! $dst_h )
+						$dst_h = $src_h;
 
-				$this->image->scaleImage( $dst_w, $dst_h );
-				return $this->update_size();
+					$frame->scaleImage( $dst_w, $dst_h );
+				}
 			}
+
+			if ( $this->animated ) {
+				$this->image = $this->image->optimizeImageLayers();
+			}
 		}
 		catch ( Exception $e ) {
 			return new WP_Error( 'image_crop_error', $e->getMessage() );
@@ -392,8 +422,18 @@
 		 * (GD rotates counter-clockwise)
 		 */
 		try {
-			$this->image->rotateImage( new ImagickPixel('none'), 360-$angle );
+			if ( $this->animated ) {
+				$this->image = $this->image->coalesceImages();
+			}
 
+			foreach ($this->image as $frame) {
+				$frame->rotateImage( new ImagickPixel('none'), 360-$angle );
+			}
+
+			if ( $this->animated ) {
+				$this->image = $this->image->optimizeImageLayers();
+			}
+
 			// Since this changes the dimensions of the image, update the size.
 			$result = $this->update_size();
 			if ( is_wp_error( $result ) )
@@ -419,11 +459,21 @@
 	 */
 	public function flip( $horz, $vert ) {
 		try {
-			if ( $horz )
-				$this->image->flipImage();
+			if ( $this->animated ) {
+				$this->image = $this->image->coalesceImages();
+			}
 
-			if ( $vert )
-				$this->image->flopImage();
+			foreach ($this->image as $frame) {
+				if ( $horz )
+					$frame->flipImage();
+
+				if ( $vert )
+					$frame->flopImage();
+			}
+
+			if ( $this->animated ) {
+				$this->image = $this->image->optimizeImageLayers();
+			}
 		}
 		catch ( Exception $e ) {
 			return new WP_Error( 'image_flip_error', $e->getMessage() );
@@ -477,8 +527,13 @@
 			$orig_format = $this->image->getImageFormat();
 
 			$this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
-			$this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
 
+			if ( $this->animated ) {
+				$this->make_image( $filename, array( $image, 'writeImages' ), array( $filename, true ) );
+			} else {
+				$this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
+			}
+
 			// Reset original Format
 			$this->image->setImageFormat( $orig_format );
 		}
@@ -519,8 +574,13 @@
 
 			// Output stream of image content
 			header( "Content-Type: $mime_type" );
-			print $this->image->getImageBlob();
 
+			if ( $this->animated ) {
+				print $this->image->getImagesBlob();
+			} else {
+				print $this->image->getImageBlob();
+			}
+
 			// Reset Image to original Format
 			$this->image->setImageFormat( $this->get_extension( $this->mime_type ) );
 		}
Index: src/wp-includes/class-wp-image-editor.php
===================================================================
--- src/wp-includes/class-wp-image-editor.php	(revision 36486)
+++ src/wp-includes/class-wp-image-editor.php	(working copy)
@@ -20,6 +20,14 @@
 	protected $default_quality = 90;
 
 	/**
+	 * Whether this is an animated image.
+	 *
+	 * @access protected
+	 * @var bool
+	 */
+	protected $animated = null;
+
+	/**
 	 * Each instance handles a single file.
 	 *
 	 * @param string $file Path to the file to load.
@@ -491,5 +499,10 @@
 
 		return $extensions[0];
 	}
+
+	public function is_animated() {
+		return $this->animated;
+	}
+
 }
 
