Index: src/wp-admin/js/customize-controls.js
===================================================================
--- src/wp-admin/js/customize-controls.js	(revision 32819)
+++ src/wp-admin/js/customize-controls.js	(working copy)
@@ -1840,11 +1840,13 @@
 	 * @augments wp.customize.Control
 	 * @augments wp.customize.Class
 	 */
-	api.HeaderControl = api.Control.extend({
+	api.CropControl = api.Control.extend({
 		ready: function() {
-			this.btnRemove = $('#customize-control-header_image .actions .remove');
-			this.btnNew    = $('#customize-control-header_image .actions .new');
+			var control = this
 
+			this.btnRemove = control.container.find('.actions .remove');
+			this.btnNew    = control.container.find('.actions .new');
+
 			_.bindAll(this, 'openMedia', 'removeImage');
 
 			this.btnNew.on( 'click', this.openMedia );
@@ -1854,17 +1856,17 @@
 
 			new api.HeaderTool.CurrentView({
 				model: api.HeaderTool.currentHeader,
-				el: '#customize-control-header_image .current .container'
+				el: control.container.find('.current .container')
 			});
 
 			new api.HeaderTool.ChoiceListView({
 				collection: api.HeaderTool.UploadsList = new api.HeaderTool.ChoiceList(),
-				el: '#customize-control-header_image .choices .uploaded .list'
+				el: control.container.find('.choices .uploaded .list')
 			});
 
 			new api.HeaderTool.ChoiceListView({
 				collection: api.HeaderTool.DefaultsList = new api.HeaderTool.DefaultsList(),
-				el: '#customize-control-header_image .choices .default .list'
+				el: control.container.find('.choices .default .list')
 			});
 
 			api.HeaderTool.combinedList = api.HeaderTool.CombinedList = new api.HeaderTool.CombinedList([
@@ -2096,7 +2098,15 @@
 			api.HeaderTool.currentHeader.trigger('hide');
 			api.HeaderTool.CombinedList.trigger('control:removeImage');
 		}
+	});
 
+	/**
+	 * @class
+	 * @augments wp.customize.Control
+	 * @augments wp.customize.Class
+	 */
+	api.HeaderControl = api.CropControl.extend({
+
 	});
 
 	/**
@@ -2699,6 +2709,7 @@
 		media:      api.MediaControl,
 		upload:     api.UploadControl,
 		image:      api.ImageControl,
+		cropimage:  api.CropControl,
 		header:     api.HeaderControl,
 		background: api.BackgroundControl,
 		theme:      api.ThemeControl
Index: src/wp-includes/class-wp-customize-control.php
===================================================================
--- src/wp-includes/class-wp-customize-control.php	(revision 32819)
+++ src/wp-includes/class-wp-customize-control.php	(working copy)
@@ -997,32 +997,41 @@
 }
 
 /**
- * Customize Header Image Control class.
+ * Customize Cropped Image Control class.
  *
- * @since 3.4.0
+ * @since 4.3.0
  *
  * @see WP_Customize_Image_Control
  */
-class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
-	public $type = 'header';
-	public $uploaded_headers;
-	public $default_headers;
+abstract class WP_Customize_Cropped_Image_Control extends WP_Customize_Image_Control {
+	public $type = 'cropimage';
 
+	protected $width  = 150;
+	protected $height = 150;
+	protected $flex_width  = false;
+	protected $flex_height = false;
+	protected $localized_name;
+	protected $current_title = '';
+
+	protected $uploaded_images = array();
+	protected $default_images  = array();
+
 	/**
+	 * Constructor.
+	 *
+	 * @since 3.4.0
+	 * @uses WP_Customize_Image_Control::__construct()
+	 *
 	 * @param WP_Customize_Manager $manager
 	 */
-	public function __construct( $manager ) {
-		parent::__construct( $manager, 'header_image', array(
-			'label'    => __( 'Header Image' ),
-			'settings' => array(
-				'default' => 'header_image',
-				'data'    => 'header_image_data',
-			),
-			'section'  => 'header_image',
-			'removed'  => 'remove-header',
-			'get_url'  => 'get_header_image',
-		) );
+	public function __construct( $manager, $id, $args ) {
+		$defaults = array(
+			'localized_name' => '_cropped_image_' . $id
+		);
 
+		$args = wp_parse_args( $args, $defaults );
+
+		parent::__construct( $manager, $id, $args );
 	}
 
 	/**
@@ -1034,20 +1043,19 @@
 
 		$this->prepare_control();
 
-		wp_localize_script( 'customize-views', '_wpCustomizeHeader', array(
+		wp_localize_script( 'customize-views', $this->localized_name, array(
 			'data' => array(
-				'width' => absint( get_theme_support( 'custom-header', 'width' ) ),
-				'height' => absint( get_theme_support( 'custom-header', 'height' ) ),
-				'flex-width' => absint( get_theme_support( 'custom-header', 'flex-width' ) ),
-				'flex-height' => absint( get_theme_support( 'custom-header', 'flex-height' ) ),
-				'currentImgSrc' => $this->get_current_image_src(),
+				'width' => absint( $this->width ),
+				'height' => absint( $this->height ),
+				'flex-width' => absint( $this->flex_width ),
+				'flex-height' => absint( $this->flex_height ),
 			),
 			'nonces' => array(
 				'add' => wp_create_nonce( 'header-add' ),
 				'remove' => wp_create_nonce( 'header-remove' ),
 			),
-			'uploads' => $this->uploaded_headers,
-			'defaults' => $this->default_headers
+			'uploads'  => $this->uploaded_images,
+			'defaults' => $this->default_images
 		) );
 
 		parent::enqueue();
@@ -1054,54 +1062,11 @@
 	}
 
 	/**
-	 *
-	 * @global Custom_Image_Header $custom_image_header
-	 */
-	public function prepare_control() {
-		global $custom_image_header;
-		if ( empty( $custom_image_header ) ) {
-			return;
-		}
-
-		// Process default headers and uploaded headers.
-		$custom_image_header->process_default_headers();
-		$this->default_headers = $custom_image_header->get_default_header_images();
-		$this->uploaded_headers = $custom_image_header->get_uploaded_header_images();
-	}
-
-	/**
 	 * @access public
 	 */
-	public function print_header_image_template() {
+	public function print_crop_image_template() {
 		?>
-		<script type="text/template" id="tmpl-header-choice">
-			<# if (data.random) { #>
-			<button type="button" class="button display-options random">
-				<span class="dashicons dashicons-randomize dice"></span>
-				<# if ( data.type === 'uploaded' ) { #>
-					<?php _e( 'Randomize uploaded headers' ); ?>
-				<# } else if ( data.type === 'default' ) { #>
-					<?php _e( 'Randomize suggested headers' ); ?>
-				<# } #>
-			</button>
-
-			<# } else { #>
-
-			<# if (data.type === 'uploaded') { #>
-				<button type="button" class="dashicons dashicons-no close"><span class="screen-reader-text"><?php _e( 'Remove image' ); ?></span></button>
-			<# } #>
-
-			<button type="button" class="choice thumbnail"
-				data-customize-image-value="{{{data.header.url}}}"
-				data-customize-header-image-data="{{JSON.stringify(data.header)}}">
-				<span class="screen-reader-text"><?php _e( 'Set image' ); ?></span>
-				<img src="{{{data.header.thumbnail_url}}}" alt="{{{data.header.alt_text || data.header.description}}}">
-			</button>
-
-			<# } #>
-		</script>
-
-		<script type="text/template" id="tmpl-header-current">
+		<script type="text/template" id="tmpl-cropped-current">
 			<# if (data.choice) { #>
 				<# if (data.random) { #>
 
@@ -1138,63 +1103,51 @@
 	}
 
 	/**
-	 * @return string|void
-	 */
-	public function get_current_image_src() {
-		$src = $this->value();
-		if ( isset( $this->get_url ) ) {
-			$src = call_user_func( $this->get_url, $src );
-			return $src;
-		}
-	}
-
-	/**
 	 * @access public
 	 */
 	public function render_content() {
-		$this->print_header_image_template();
-		$visibility = $this->get_current_image_src() ? '' : ' style="display:none" ';
-		$width = absint( get_theme_support( 'custom-header', 'width' ) );
-		$height = absint( get_theme_support( 'custom-header', 'height' ) );
+		$this->print_crop_image_template();
+
+		$width = absint( $this->width );
+		$height = absint( $this->height );
 		?>
 
-
 		<div class="customize-control-content">
 			<p class="customizer-section-intro">
 				<?php
 				if ( $width && $height ) {
-					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header size of <strong>%s &times; %s</strong> pixels.' ), $width, $height );
+					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a size of <strong>%s &times; %s</strong> pixels.' ), $width, $height );
 				} elseif ( $width ) {
-					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header width of <strong>%s</strong> pixels.' ), $width );
+					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a width of <strong>%s</strong> pixels.' ), $width );
 				} else {
-					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header height of <strong>%s</strong> pixels.' ), $height );
+					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a height of <strong>%s</strong> pixels.' ), $height );
 				}
 				?>
 			</p>
 			<div class="current">
 				<span class="customize-control-title">
-					<?php _e( 'Current header' ); ?>
+					<?php echo $this->current_title ? $this->current_title : _x( 'Current', 'cropped image' ); ?>
 				</span>
 				<div class="container">
 				</div>
 			</div>
 			<div class="actions">
-				<?php /* translators: Hide as in hide header image via the Customizer */ ?>
-				<button type="button"<?php echo $visibility ?> class="button remove"><?php _ex( 'Hide image', 'custom header' ); ?></button>
-				<?php /* translators: New as in add new header image via the Customizer */ ?>
-				<button type="button" class="button new"><?php _ex( 'Add new image', 'header image' ); ?></button>
+				<?php /* translators: Hide as in hide cropped image via the Customizer */ ?>
+				<button type="button" class="button remove"><?php _ex( 'Hide image', 'crop image' ); ?></button>
+				<?php /* translators: New as in add new cropped image via the Customizer */ ?>
+				<button type="button" class="button new"><?php _ex( 'Add new image', 'cropped image' ); ?></button>
 				<div style="clear:both"></div>
 			</div>
 			<div class="choices">
-				<span class="customize-control-title header-previously-uploaded">
-					<?php _ex( 'Previously uploaded', 'custom headers' ); ?>
+				<span class="customize-control-title cropped-image-previously-uploaded">
+					<?php _ex( 'Previously uploaded', 'cropped images' ); ?>
 				</span>
 				<div class="uploaded">
 					<div class="list">
 					</div>
 				</div>
-				<span class="customize-control-title header-default">
-					<?php _ex( 'Suggested', 'custom headers' ); ?>
+				<span class="customize-control-title cropped-image-default">
+					<?php _ex( 'Suggested', 'cropped images' ); ?>
 				</span>
 				<div class="default">
 					<div class="list">
@@ -1207,6 +1160,99 @@
 }
 
 /**
+ * Customize Header Image Control class.
+ *
+ * @since 3.4.0
+ *
+ * @see WP_Customize_Cropped_Image_Control
+ */
+class WP_Customize_Header_Image_Control extends WP_Customize_Cropped_Image_Control {
+	public $type = 'header';
+
+	/**
+	 * @param WP_Customize_Manager $manager
+	 */
+	public function __construct( $manager ) {
+		parent::__construct( $manager, 'header_image', array(
+			'label'         => __( 'Header Image' ),
+			'current_title' => __( 'Current header' ),
+			'settings' => array(
+				'default' => 'header_image',
+				'data'    => 'header_image_data',
+			),
+			'section'       => 'header_image',
+			'removed'       => 'remove-header',
+		) );
+
+		$this->width  = get_theme_support( 'custom-header', 'width' );
+		$this->height = get_theme_support( 'custom-header', 'height' );
+		$this->flex_width  = get_theme_support( 'custom-header', 'flex-width' );
+		$this->flex_height = get_theme_support( 'custom-header', 'flex-height' );
+		$this->localized_name = '_wpCustomizeHeader';
+	}
+
+	/**
+	 *
+	 * @global Custom_Image_Header $custom_image_header
+	 */
+	public function prepare_control() {
+		global $custom_image_header;
+
+		if ( empty( $custom_image_header ) ) {
+			return;
+		}
+
+		// Process default headers and uploaded headers.
+		$custom_image_header->process_default_headers();
+		$this->default_images  = $custom_image_header->get_default_header_images();
+		$this->uploaded_images = $custom_image_header->get_uploaded_header_images();
+	}
+
+	/**
+	 * @access public
+	 */
+	public function print_header_image_template() {
+		?>
+		<script type="text/template" id="tmpl-header-choice">
+			<# if (data.random) { #>
+			<button type="button" class="button display-options random">
+				<span class="dashicons dashicons-randomize dice"></span>
+				<# if ( data.type === 'uploaded' ) { #>
+					<?php _e( 'Randomize uploaded headers' ); ?>
+				<# } else if ( data.type === 'default' ) { #>
+					<?php _e( 'Randomize suggested headers' ); ?>
+				<# } #>
+			</button>
+
+			<# } else { #>
+
+			<# if (data.type === 'uploaded') { #>
+				<button type="button" class="dashicons dashicons-no close"><span class="screen-reader-text"><?php _e( 'Remove image' ); ?></span></button>
+			<# } #>
+
+			<button type="button" class="choice thumbnail"
+				data-customize-image-value="{{{data.header.url}}}"
+				data-customize-header-image-data="{{JSON.stringify(data.header)}}">
+				<span class="screen-reader-text"><?php _e( 'Set image' ); ?></span>
+				<img src="{{{data.header.thumbnail_url}}}" alt="{{{data.header.alt_text || data.header.description}}}">
+			</button>
+
+			<# } #>
+		</script>
+		<?php
+	}
+
+	/**
+	 * @access public
+	 */
+	public function render_content() {
+		$this->print_header_image_template();
+
+		parent::render_content();
+	}
+}
+
+/**
  * Customize Theme Control class.
  *
  * @since 4.2.0
Index: src/wp-includes/js/customize-views.js
===================================================================
--- src/wp-includes/js/customize-views.js	(revision 32819)
+++ src/wp-includes/js/customize-views.js	(working copy)
@@ -16,7 +16,7 @@
 	 * @augments wp.Backbone.View
 	 */
 	api.HeaderTool.CurrentView = wp.Backbone.View.extend({
-		template: wp.template('header-current'),
+		template: wp.template('cropped-current'),
 
 		initialize: function() {
 			this.listenTo(this.model, 'change', this.render);
