Index: wp-includes/theme.php
===================================================================
--- wp-includes/theme.php	(revision 19792)
+++ wp-includes/theme.php	(working copy)
@@ -1547,16 +1547,27 @@
 
 	foreach ( (array) $headers as $header ) {
 		$url = esc_url_raw( $header->guid );
+		$header_data = wp_get_attachment_metadata( $header->ID );
 		$header = basename($url);
 		$header_images[$header] = array();
 		$header_images[$header]['url'] =  $url;
 		$header_images[$header]['thumbnail_url'] =  $url;
 		$header_images[$header]['uploaded'] = true;
+		$header_images[$header]['width'] = $header_data['width'];
+		$header_images[$header]['height'] = $header_data['height'];
 	}
 
 	return $header_images;
 }
 
+function get_header_image_width() {
+	return get_theme_mod( 'header_image_width', HEADER_IMAGE_WIDTH );
+}
+
+function get_header_image_height() {
+	return get_theme_mod( 'header_image_height', HEADER_IMAGE_HEIGHT );
+}
+
 /**
  * Add callbacks for image header display.
  *
Index: wp-admin/custom-header.php
===================================================================
--- wp-admin/custom-header.php	(revision 19792)
+++ wp-admin/custom-header.php	(working copy)
@@ -225,10 +225,17 @@
 			} else {
 				$this->process_default_headers();
 				$uploaded = get_uploaded_header_images();
-				if ( isset( $uploaded[$_POST['default-header']] ) )
+				if ( isset( $uploaded[$_POST['default-header']] ) ) {
 					set_theme_mod( 'header_image', esc_url( $uploaded[$_POST['default-header']]['url'] ) );
-				elseif ( isset( $this->default_headers[$_POST['default-header']] ) )
+					set_theme_mod( 'header_image_width', $uploaded[$_POST['default-header']]['width'] );
+					set_theme_mod( 'header_image_height', $uploaded[$_POST['default-header']]['height'] );
+				} elseif ( isset( $this->default_headers[$_POST['default-header']] ) ) {
 					set_theme_mod( 'header_image', esc_url( $this->default_headers[$_POST['default-header']]['url'] ) );
+					$width = empty( $this->default_headers[$_POST['default-header']]['width'] )? HEADER_IMAGE_WIDTH : $this->default_headers[$_POST['default-header']]['width'];
+					$height = empty( $this->default_headers[$_POST['default-header']]['height'] )? HEADER_IMAGE_HEIGHT : $this->default_headers[$_POST['default-header']]['height'];
+					set_theme_mod( 'header_image_width', $width );
+					set_theme_mod( 'header_image_height', $height );
+				}
 			}
 		}
 	}
@@ -438,13 +445,20 @@
 		jQuery('img#upload').imgAreaSelect({
 			handles: true,
 			keys: true,
-			aspectRatio: xinit + ':' + yinit,
 			show: true,
 			x1: 0,
 			y1: 0,
 			x2: xinit,
 			y2: yinit,
+			<?php
+			$header_support = get_theme_support( 'custom-header' );
+			if ( ! isset( $header_support[ 0 ] ) || empty( $header_support[ 0 ][ 'flex-height' ] ) || !$header_support[ 0 ][ 'flex-height' ] ) {
+			?>
+			aspectRatio: xinit + ':' + yinit,
 			maxHeight: <?php echo HEADER_IMAGE_HEIGHT; ?>,
+			<?php
+			}
+			?>
 			maxWidth: <?php echo HEADER_IMAGE_WIDTH; ?>,
 			onInit: function () {
 				jQuery('#width').val(xinit);
@@ -492,7 +506,7 @@
 	  call_user_func( $this->admin_image_div_callback );
 	} else {
 	?>
-	<div id="headimg" style="max-width:<?php echo HEADER_IMAGE_WIDTH; ?>px;height:<?php echo HEADER_IMAGE_HEIGHT; ?>px;background-image:url(<?php esc_url ( header_image() ) ?>);">
+	<div id="headimg" style="max-width:<?php echo get_header_image_width(); ?>px;height:<?php echo get_header_image_height(); ?>px;background-image:url(<?php esc_url ( header_image() ) ?>);">
 		<?php
 		if ( 'blank' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || '' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || ! $this->header_text() )
 			$style = ' style="display:none;"';
@@ -510,7 +524,16 @@
 <th scope="row"><?php _e( 'Upload Image' ); ?></th>
 <td>
 	<p><?php _e( 'You can upload a custom header image to be shown at the top of your site instead of the default one. On the next screen you will be able to crop the image.' ); ?><br />
-	<?php printf( __( 'Images of exactly <strong>%1$d &times; %2$d pixels</strong> will be used as-is.' ), HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT ); ?></p>
+	<?php
+	$header_support = get_theme_support( 'custom-header' );
+	if ( ! isset( $header_support[ 0 ] ) || empty( $header_support[ 0 ][ 'flex-height' ] ) || !$header_support[ 0 ][ 'flex-height' ] ) {
+		printf( __( 'Images of exactly <strong>%1$d &times; %2$d pixels</strong> will be used as-is.' ), HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT );
+	} else {
+		printf( __( 'Images should be at least <strong>%1$d pixels</strong> wide.' ), HEADER_IMAGE_WIDTH );
+		if ( !empty( $header_support[ 0 ][ 'suggested-height' ] ) )
+			printf( __( ' Suggested height is <strong>%1$d pixels</strong>.' ), absint( $header_support[ 0 ][ 'suggested-height' ] ) );
+	}
+	?></p>
 	<form enctype="multipart/form-data" id="upload-form" method="post" action="<?php echo esc_attr( add_query_arg( 'step', 2 ) ) ?>">
 	<p>
 		<label for="upload"><?php _e( 'Choose an image from your computer:' ); ?></label><br />
@@ -662,7 +685,9 @@
 
 		list($width, $height, $type, $attr) = getimagesize( $file );
 
-		if ( $width == HEADER_IMAGE_WIDTH && $height == HEADER_IMAGE_HEIGHT ) {
+		$header_support = get_theme_support( 'custom-header' );
+		// If flexible height isn't supported and the image is the exact right size
+		if ( ( !isset( $header_support[ 0 ] ) || empty( $header_support[ 0 ][ 'flex-height' ] ) || !empty( $header_support[ 0 ][ 'flex-height' ] ) ) && $width == HEADER_IMAGE_WIDTH && $height == HEADER_IMAGE_HEIGHT ) {
 			// Add the meta-data
 			wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) );
 			update_post_meta( $id, '_wp_attachment_is_custom_header', get_option('stylesheet' ) );
@@ -733,7 +758,13 @@
 		$attachment_id = absint( $_POST['attachment_id'] );
 		$original = get_attached_file($attachment_id);
 
-		$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT );
+		$header_support = get_theme_support( 'custom-header' );
+		if ( isset( $header_support[ 0 ] ) && !empty( $header_support[ 0 ][ 'flex-height' ] ) )
+			$dst_height = (int) $_POST['height'] * ( HEADER_IMAGE_WIDTH / $_POST['width'] );
+		else
+			$dst_height = HEADER_IMAGE_HEIGHT;
+
+		$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], HEADER_IMAGE_WIDTH, $dst_height );
 		if ( is_wp_error( $cropped ) )
 			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
 
