diff --git a/src/js/_enqueues/lib/image-edit.js b/src/js/_enqueues/lib/image-edit.js
index b41e93f55d..8f86aef246 100644
--- a/src/js/_enqueues/lib/image-edit.js
+++ b/src/js/_enqueues/lib/image-edit.js
@@ -143,17 +143,12 @@
 	 * @return {void}
 	 */
 	init : function(postid) {
-		var t = this, old = $('#image-editor-' + t.postid),
-			x = t.intval( $('#imgedit-x-' + postid).val() ),
-			y = t.intval( $('#imgedit-y-' + postid).val() );
+		var t = this, old = $('#image-editor-' + t.postid);
 
 		if ( t.postid !== postid && old.length ) {
 			t.close(t.postid);
 		}
 
-		t.hold.w = t.hold.ow = x;
-		t.hold.h = t.hold.oh = y;
-		t.hold.xy_ratio = x / y;
 		t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() );
 		t.postid = postid;
 		$('#imgedit-response-' + postid).empty();
@@ -188,6 +183,28 @@
 		$( document ).on( 'image-editor-ui-ready', this.focusManager );
 	},
 
+	/**
+	 * Calculate the image size and save it to memory.
+	 *
+	 * @since 6.6.0
+	 *
+	 * @memberof imageEdit
+	 *
+	 * @param {number} postid The post ID.
+	 *
+	 * @return {void}
+	 */
+	calculateImgSize: function (postid) {
+		var t = this,
+		x = t.intval( $('#imgedit-x-' + postid).val() ),
+		y = t.intval( $('#imgedit-y-' + postid).val() );
+		t.hold.w = t.hold.ow = x;
+		t.hold.h = t.hold.oh = y;
+		t.hold.xy_ratio = x / y;
+		t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() );
+		t.currentCropSelection = null;
+	},
+
 	/**
 	 * Toggles the wait/load icon in the editor.
 	 *
@@ -525,7 +542,7 @@
 			for ( n in history ) {
 				i = history[n];
 				if ( i.hasOwnProperty('c') ) {
-					op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } };
+					op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h, 'r': i.c.r } };
 				} else if ( i.hasOwnProperty('r') ) {
 					op[n] = { 'r': i.r.r };
 				} else if ( i.hasOwnProperty('f') ) {
@@ -860,6 +877,7 @@
 		if ( 'undefined' === typeof this.hold.sizer ) {
 			this.init( postid );
 		}
+		this.calculateImgSize( postid );
 
 		this.initCrop(postid, img, parent);
 		this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'width': img.innerWidth(), 'height': img.innerHeight() } );
@@ -945,13 +963,16 @@
 				 *
 				 * @return {void}
 				 */
-				parent.children().on( 'mousedown, touchstart', function(e){
-					var ratio = false, sel, defRatio;
-
-					if ( e.shiftKey ) {
-						sel = t.iasapi.getSelection();
-						defRatio = t.getSelRatio(postid);
-						ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio;
+				parent.children().on( 'mousedown touchstart', function(e) {
+					var ratio = false,
+					 	sel = t.iasapi.getSelection(),
+					 	cx = t.intval($('#imgedit-crop-width-' + postid).val()),
+					 	cy = t.intval($('#imgedit-crop-height-' + postid).val());
+
+					if ( cx && cy ) {
+						ratio = t.getSelRatio(postid);
+					} else if ( e.shiftKey && sel && sel.width && sel.height ) {
+						ratio = sel.width + ':' + sel.height;
 					}
 
 					t.iasapi.setOptions({
@@ -1001,10 +1022,16 @@
 			 */
 			onSelectChange: function(img, c) {
 				var sizer = imageEdit.hold.sizer;
-				selW.val( imageEdit.round(c.width / sizer) );
-				selH.val( imageEdit.round(c.height / sizer) );
-				selX.val( imageEdit.round(c.x1 / sizer) );
-				selY.val( imageEdit.round(c.y1 / sizer) );
+				var oldSel = imageEdit.currentCropSelection;
+
+				if (oldSel != null && oldSel.width == c.width && oldSel.height == c.height) {
+					return;
+				}
+
+				selW.val( Math.min(imageEdit.hold.w, imageEdit.round(c.width / sizer)) );
+				selH.val( Math.min(imageEdit.hold.h, imageEdit.round(c.height / sizer)) );
+
+				t.currentCropSelection = c;
 			}
 		});
 	},
@@ -1023,6 +1050,10 @@
 	 */
 	setCropSelection : function(postid, c) {
 		var sel;
+			selW = $('#imgedit-sel-width-' + postid),
+			selH = $('#imgedit-sel-height-' + postid),
+			sizer = this.hold.sizer,
+			hold = this.hold;
 
 		c = c || 0;
 
@@ -1037,7 +1068,15 @@
 			return false;
 		}
 
-		sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height };
+		// adjust the selection within the bounds of the image on 100% scale
+		var excessW = hold.w - ( Math.round(c.x1 / sizer) + parseInt(selW.val()) );
+		var excessH = hold.h - ( Math.round(c.y1 / sizer) + parseInt(selH.val()) );
+		var x = Math.round( c.x1 / sizer ) + Math.min( 0, excessW );
+		var y = Math.round( c.y1 / sizer ) + Math.min( 0, excessH );
+
+		// use 100% scaling to prevent rounding errors
+		sel = { 'r': 1, 'x': x, 'y': y, 'w': selW.val(), 'h': selH.val() };
+
 		this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1);
 		$('#imgedit-selection-' + postid).val( JSON.stringify(sel) );
 	},
@@ -1165,6 +1204,11 @@
 		}
 		this.closePopup(t);
 		this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce);
+
+		// Clear the selection fields after rotating.
+		$('#imgedit-sel-width-' + postid).val('');
+		$('#imgedit-sel-height-' + postid).val('');
+		this.currentCropSelection = null;
 	},
 
 	/**
@@ -1187,6 +1231,11 @@
 		}
 		this.closePopup(t);
 		this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce);
+
+		// Clear the selection fields after flipping.
+		$('#imgedit-sel-width-' + postid).val('');
+		$('#imgedit-sel-height-' + postid).val('');
+		this.currentCropSelection = null;
 	},
 
 	/**
@@ -1223,6 +1272,7 @@
 		$('#imgedit-sel-height-' + postid).val('');
 		$('#imgedit-start-x-' + postid).val('0');
 		$('#imgedit-start-y-' + postid).val('0');
+		this.currentCropSelection = null;
 	},
 
 	/**
@@ -1312,6 +1362,8 @@
 			img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(),
 			sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi;
 
+		this.currentCropSelection = null;
+
 		if ( false === this.validateNumeric( el ) ) {
 			return;
 		}
@@ -1335,18 +1387,19 @@
 			if ( x2 > imgw ) {
 				x1 = 0;
 				x2 = imgw;
-				elX.val( Math.round( x2 / sizer ) );
+				elX.val( Math.min( this.hold.w, Math.round( x2 / sizer ) ) );
 			}
 
 			if ( y2 > imgh ) {
 				y1 = 0;
 				y2 = imgh;
-				elY.val( Math.round( y2 / sizer ) );
+				elY.val( Math.min( this.hold.h, Math.round( y2 / sizer ) ) );
 			}
 
 			ias.setSelection( x1, y1, x2, y2 );
 			ias.update();
 			this.setCropSelection(postid, ias.getSelection());
+			this.currentCropSelection = ias.getSelection();
 		}
 	},
 
diff --git a/src/wp-admin/includes/image-edit.php b/src/wp-admin/includes/image-edit.php
index b8ea443cd4..fec5220be9 100644
--- a/src/wp-admin/includes/image-edit.php
+++ b/src/wp-admin/includes/image-edit.php
@@ -735,10 +735,10 @@ function image_edit_apply_changes( $image, $changes ) {
 					$w    = $size['width'];
 					$h    = $size['height'];
 
-					$scale = 1 / _image_get_preview_ratio( $w, $h ); // Discard preview scaling.
+					$scale = isset($sel->r) ? $sel->r : 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.
+					$scale = isset($sel->r) ? $sel->r : 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;
