Index: src/wp-admin/css/themes.css
===================================================================
--- src/wp-admin/css/themes.css	(revision 27915)
+++ src/wp-admin/css/themes.css	(working copy)
@@ -1283,6 +1283,7 @@
 .more-filters-container .filtering-by .tag {
 	background: #fff;
 	border: 1px solid #e5e5e5;
+	-webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
 	box-shadow: 0 1px 1px rgba(0,0,0,0.04);
 	font-size: 11px;
 	margin: 0 5px;
Index: src/wp-includes/css/media-views.css
===================================================================
--- src/wp-includes/css/media-views.css	(revision 27915)
+++ src/wp-includes/css/media-views.css	(working copy)
@@ -1640,10 +1640,8 @@
 }
 
 .image-details .advanced-toggle {
-	font-style: italic;
 	color: #666;
 	text-decoration: none;
-	margin: 20px;
 	display: block;
 }
 
@@ -1663,6 +1661,39 @@
 	margin-top: 0;
 }
 
+.image-details .embed-media-settings .size {
+	margin-bottom: 4px;
+}
+
+.image-details .custom-size span {
+	display: block;
+}
+
+.image-details .custom-size label {
+	display: block;
+	float: left;
+}
+
+.image-details .custom-size span small {
+	color: #999;
+	font-size: inherit;
+}
+
+.image-details .custom-size input {
+	width: 5em;
+}
+
+.image-details .custom-size .sep {
+	float: left;
+	margin: 26px 6px 0 6px;
+}
+
+.image-details .custom-size::after {
+    content: '';
+	display: table;
+    clear: both;
+}
+
 .media-embed .thumbnail {
 	max-width: 100%;
 	max-height: 200px;
@@ -1724,7 +1755,8 @@
 }
 
 .image-details .embed-media-settings .setting input.link-to-custom,
-.image-details .embed-media-settings .link-target {
+.image-details .embed-media-settings .link-target,
+.image-details .embed-media-settings .custom-size {
 	margin-left: 27%;
 	width: 70%;
 }
@@ -2003,8 +2035,8 @@
 		margin-left: 0;
 	}
 
-	.image-details .link-target {
-		width: 100%;
+	.image-details .embed-media-settings .custom-size {
+		margin-left: 20px;
 	}
 
 	.media-selection {
Index: src/wp-includes/js/media-models.js
===================================================================
--- src/wp-includes/js/media-models.js	(revision 27915)
+++ src/wp-includes/js/media-models.js	(working copy)
@@ -369,6 +369,9 @@
 			this.on( 'change:size', this.updateSize, this );
 
 			this.setLinkTypeFromUrl();
+
+			this.set( 'aspectRatio', attributes.customWidth / attributes.customHeight );
+			this.set( 'originalUrl', attributes.url );
 		},
 
 		bindAttachmentListeners: function() {
@@ -447,6 +450,13 @@
 				return;
 			}
 
+			if ( this.get( 'size' ) === 'custom' ) {
+				this.set( 'width', this.get( 'customWidth' ) );
+				this.set( 'height', this.get( 'customHeight' ) );
+				this.set( 'url', this.get( 'originalUrl' ) );
+				return;
+			}
+
 			size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];
 
 			if ( ! size ) {
Index: src/wp-includes/js/media-views.js
===================================================================
--- src/wp-includes/js/media-views.js	(revision 27915)
+++ src/wp-includes/js/media-views.js	(working copy)
@@ -6059,7 +6059,11 @@
 		events: _.defaults( media.view.Settings.AttachmentDisplay.prototype.events, {
 			'click .edit-attachment': 'editAttachment',
 			'click .replace-attachment': 'replaceAttachment',
-			'click .advanced-toggle': 'toggleAdvanced'
+			'click .advanced-toggle': 'toggleAdvanced',
+			'change [data-setting="customWidth"]': 'syncCustomSize',
+			'change [data-setting="customHeight"]': 'syncCustomSize',
+			'keyup [data-setting="customWidth"]': 'syncCustomSize',
+			'keyup [data-setting="customHeight"]': 'syncCustomSize'
 		} ),
 		initialize: function() {
 			// used in AttachmentDisplay.prototype.updateLinkTo
@@ -6066,6 +6070,7 @@
 			this.options.attachment = this.model.attachment;
 			this.listenTo( this.model, 'change:url', this.updateUrl );
 			this.listenTo( this.model, 'change:link', this.toggleLinkSettings );
+			this.listenTo( this.model, 'change:size', this.toggleCustomSize );
 			media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments );
 		},
 
@@ -6123,6 +6128,29 @@
 			}
 		},
 
+		toggleCustomSize: function() {
+			if ( this.model.get( 'size' ) !== 'custom' ) {
+				this.$( '.custom-size' ).addClass('hidden');
+			} else {
+				this.$( '.custom-size' ).removeClass('hidden');
+			}
+		},
+
+		syncCustomSize: function( event ) {
+			var dimension = $( event.target ).data('setting'),
+				value;
+
+			if ( dimension === 'customWidth' ) {
+				value = Math.round( 1 / this.model.get( 'aspectRatio' ) * $( event.target ).val() );
+				this.model.set( 'customHeight', value, { silent: true } );
+				this.$( '[data-setting="customHeight"]' ).val( value );
+			} else {
+				value = Math.round( this.model.get( 'aspectRatio' ) * $( event.target ).val() );
+				this.$( '[data-setting="customWidth"]' ).val( value );
+				this.model.set( 'customWidth', value, { silent: true } );
+			}
+		},
+
 		toggleAdvanced: function( event ) {
 			var $advanced = $( event.target ).closest( '.advanced' );
 			event.preventDefault();
Index: src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js
===================================================================
--- src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js	(revision 27915)
+++ src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js	(working copy)
@@ -123,7 +123,9 @@
 			url: false,
 			height: '',
 			width: '',
-			size: false,
+			customWidth: '',
+			customHeight: '',
+			size: 'custom',
 			caption: '',
 			alt: '',
 			align: 'none',
@@ -139,12 +141,12 @@
 		metadata.url = dom.getAttrib( imageNode, 'src' );
 		metadata.alt = dom.getAttrib( imageNode, 'alt' );
 		metadata.title = dom.getAttrib( imageNode, 'title' );
-
 		width = dom.getAttrib( imageNode, 'width' ) || imageNode.width;
 		height = dom.getAttrib( imageNode, 'height' ) || imageNode.height;
-
 		metadata.width = parseInt( width, 10 );
 		metadata.height = parseInt( height, 10 );
+		metadata.customWidth = metadata.width;
+		metadata.customHeight = metadata.height;
 
 		classes = tinymce.explode( imageNode.className, ' ' );
 		extraClasses = [];
@@ -199,9 +201,13 @@
 		return metadata;
 	}
 
+	function hasTextContent( node ) {
+		return node && !! ( node.textContent || node.innerText );
+	}
+
 	function updateImage( imageNode, imageData ) {
-		var classes, className, width, node, html, parent, wrap,
-			captionNode, dd, dl, id, attrs, linkAttrs,
+		var classes, className, node, html, parent, wrap, linkNode,
+			captionNode, dd, dl, id, attrs, linkAttrs, width, height,
 			dom = editor.dom;
 
 		classes = tinymce.explode( imageData.extraClasses, ' ' );
@@ -216,15 +222,23 @@
 
 		if ( imageData.attachment_id ) {
 			classes.push( 'wp-image-' + imageData.attachment_id );
-			if ( imageData.size ) {
+			if ( imageData.size && imageData.size !== 'custom' ) {
 				classes.push( 'size-' + imageData.size );
 			}
 		}
 
+		width = imageData.width;
+		height = imageData.height;
+
+		if ( imageData.size === 'custom' ) {
+			width = imageData.customWidth;
+			height = imageData.customHeight;
+		}
+
 		attrs = {
 			src: imageData.url,
-			width: imageData.width || null,
-			height: imageData.height || null,
+			width: width || null,
+			height: height || null,
 			alt: imageData.alt,
 			title: imageData.title || null,
 			'class': classes.join( ' ' ) || null
@@ -239,7 +253,8 @@
 			'class': imageData.linkClassName || null
 		};
 
-		if ( imageNode.parentNode.nodeName === 'A' ) {
+		if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' && ! hasTextContent( imageNode.parentNode ) ) {
+			// Update or remove an existing link wrapped around the image
 			if ( imageData.linkUrl ) {
 				dom.setAttribs( imageNode.parentNode, linkAttrs );
 			} else {
@@ -246,13 +261,21 @@
 				dom.remove( imageNode.parentNode, true );
 			}
 		} else if ( imageData.linkUrl ) {
-			html = dom.createHTML( 'a', linkAttrs, dom.getOuterHTML( imageNode ) );
-			dom.outerHTML( imageNode, html );
+			if ( linkNode = dom.getParent( imageNode, 'a' ) ) {
+				// The image is inside a link together with other nodes,
+				// or is nested in another node, move it out
+				dom.insertAfter( imageNode, linkNode );
+			}
+
+			// Add link wrapped around the image
+			linkNode = dom.create( 'a', linkAttrs );
+			imageNode.parentNode.insertBefore( linkNode, imageNode );
+			linkNode.appendChild( imageNode );
 		}
 
 		captionNode = editor.dom.getParent( imageNode, '.mceTemp' );
 
-		if ( imageNode.parentNode.nodeName === 'A' ) {
+		if ( imageNode.parentNode && imageNode.parentNode.nodeName === 'A' && ! hasTextContent( imageNode.parentNode ) ) {
 			node = imageNode.parentNode;
 		} else {
 			node = imageNode;
@@ -259,11 +282,12 @@
 		}
 
 		if ( imageData.caption ) {
-			width = parseInt( imageData.width, 10 );
+
 			id = imageData.attachment_id ? 'attachment_' + imageData.attachment_id : null;
-			className = 'wp-caption align' + imageData.align;
+			className = 'wp-caption align' + ( imageData.align || 'none' );
 
 			if ( ! editor.getParam( 'wpeditimage_html5_captions' ) ) {
+				width = parseInt( width, 10 );
 				width += 10;
 			}
 
@@ -312,7 +336,7 @@
 		}
 
 		editor.nodeChanged();
-		// refresh the toolbar
+		// Refresh the toolbar
 		addToolbar( imageNode );
 	}
 
@@ -324,8 +348,6 @@
 			return;
 		}
 
-		editor.undoManager.add();
-
 		frame = wp.media({
 			frame: 'image',
 			state: 'image-details',
@@ -333,8 +355,10 @@
 		} );
 
 		callback = function( imageData ) {
-			updateImage( img, imageData );
 			editor.focus();
+			editor.undoManager.transact( function() {
+				updateImage( img, imageData );
+			} );
 			frame.detach();
 		};
 
Index: src/wp-includes/media-template.php
===================================================================
--- src/wp-includes/media-template.php	(revision 27915)
+++ src/wp-includes/media-template.php	(working copy)
@@ -689,7 +689,7 @@
 
 					<# if ( data.attachment ) { #>
 						<# if ( 'undefined' !== typeof data.attachment.sizes ) { #>
-							<label class="setting">
+							<label class="setting size">
 								<span><?php _e('Size'); ?></span>
 								<select class="size" name="size"
 									data-setting="size"
@@ -705,18 +705,25 @@
 										'full'      => __('Full Size'),
 									) );
 
+
 									foreach ( $sizes as $value => $name ) : ?>
 										<#
 										var size = data.sizes['<?php echo esc_js( $value ); ?>'];
 										if ( size ) { #>
-											<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, 'full' ); ?>>
+											<option value="<?php echo esc_attr( $value ); ?>">
 												<?php echo esc_html( $name ); ?> &ndash; {{ size.width }} &times; {{ size.height }}
 											</option>
 										<# } #>
 									<?php endforeach; ?>
+									<option value="<?php echo esc_attr( 'custom' ); ?>">
+										<?php _e( 'Custom Size' ); ?>
+									</option>
 								</select>
 							</label>
 						<# } #>
+							<div class="custom-size<# if ( data.model.size !== 'custom' ) { #> hidden<# } #>">
+								<label><span><?php _e( 'Width' ); ?> <small>(px)</small></span> <input data-setting="customWidth" type="number" step="1" value="{{ data.model.customWidth }}" /></label><span class="sep">&times;</span><label><span><?php _e( 'Height' ); ?> <small>(px)</small></span><input data-setting="customHeight" type="number" step="1" value="{{ data.model.customHeight }}" /></label>
+							</div>
 					<# } #>
 
 					<div class="setting link-to">
@@ -744,7 +751,7 @@
 						<input type="text" class="link-to-custom" data-setting="linkUrl" />
 					</div>
 					<div class="advanced">
-						<a class="advanced-toggle" href="#"><?php _e('Show advanced options'); ?></a>
+						<h3><a class="advanced-toggle" href="#"><?php _e('Advanced Options'); ?></a></h3>
 						<div class="hidden">
 							<label class="setting title-text">
 								<span><?php _e('Image Title Attribute'); ?></span>
