Index: wp-includes/class-wp-customize.php
===================================================================
--- wp-includes/class-wp-customize.php	(revision 20186)
+++ wp-includes/class-wp-customize.php	(working copy)
@@ -479,7 +479,7 @@
 			'section'           => 'header',
 			'sanitize_callback' => 'sanitize_hexcolor',
 			'control'           => 'color',
-			'default'           => defined( 'HEADER_TEXTCOLOR' ) ? HEADER_TEXTCOLOR : ''
+			'default'           => get_theme_support( 'custom-header', 'default-text-color' ),
 		) );
 
 		/*
@@ -505,7 +505,7 @@
 			'control' => 'checkbox',
 			 // @todo
 			 // not the default, it's the value.
-			 // value is saved in get_theme_support( 'custom-header' )[0][ 'random-default' ]
+			 // value is saved in get_theme_support( 'custom-header', 'random-default' )
 			'default' => 'random-default-image'
 		) );
 
@@ -522,7 +522,7 @@
 			'label'             => 'Background Color',
 			'section'           => 'background',
 			'control'           => 'color',
-			'default'           => defined( 'BACKGROUND_COLOR' ) ? BACKGROUND_COLOR : '',
+			'default'           => get_theme_support( 'custom-background', 'default-color' ),
 			'sanitize_callback' => 'sanitize_hexcolor',
 		) );
 
Index: wp-includes/theme.php
===================================================================
--- wp-includes/theme.php	(revision 20186)
+++ wp-includes/theme.php	(working copy)
@@ -897,14 +897,11 @@
  * Retrieve text color for custom header.
  *
  * @since 2.1.0
- * @uses HEADER_TEXTCOLOR
  *
  * @return string
  */
 function get_header_textcolor() {
-	$default = defined('HEADER_TEXTCOLOR') ? HEADER_TEXTCOLOR : '';
-
-	return get_theme_mod('header_textcolor', $default);
+	return get_theme_mod('header_textcolor', get_theme_support( 'custom-header', 'default-text-color' ) );
 }
 
 /**
@@ -920,13 +917,11 @@
  * Retrieve header image for custom header.
  *
  * @since 2.1.0
- * @uses HEADER_IMAGE
  *
  * @return string
  */
 function get_header_image() {
-	$default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : '';
-	$url = get_theme_mod( 'header_image', $default );
+	$url = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
 
 	if ( 'remove-header' == $url )
 		return false;
@@ -966,8 +961,7 @@
 			if ( 'random-default-image' == $header_image_mod ) {
 				$headers = $_wp_default_headers;
 			} else {
-				$is_random = get_theme_support( 'custom-header' );
-				if ( isset( $is_random[ 0 ] ) && !empty( $is_random[ 0 ][ 'random-default' ] ) )
+				if ( current_theme_supports( 'custom-header', 'random-default' ) )
 					$headers = $_wp_default_headers;
 			}
 		}
@@ -1006,14 +1000,12 @@
  * is chosen, and theme turns on random headers with add_theme_support().
  *
  * @since 3.2.0
- * @uses HEADER_IMAGE
  *
  * @param string $type The random pool to use. any|default|uploaded
  * @return boolean
  */
 function is_random_header_image( $type = 'any' ) {
-	$default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : '';
-	$header_image_mod = get_theme_mod( 'header_image', $default );
+	$header_image_mod = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
 
 	if ( 'any' == $type ) {
 		if ( 'random-default-image' == $header_image_mod || 'random-uploaded-image' == $header_image_mod || ( '' != get_random_header_image() && empty( $header_image_mod ) ) )
@@ -1075,98 +1067,51 @@
  *
  * @return object
  */
-function get_current_header_data() {
+function get_custom_header() {
 	$data = is_random_header_image()? _get_random_header_data() : get_theme_mod( 'header_image_data' );
 	$default = array(
 		'url'           => '',
 		'thumbnail_url' => '',
-		'width'         => '',
-		'height'        => '',
+		'width'         => get_theme_suppport( 'custom-header', 'width' ),
+		'height'        => get_theme_suppport( 'custom-header', 'height' ),
 	);
 	return (object) wp_parse_args( $data, $default );
 }
 
 /**
- * Get the header image width.
- *
- * @since 3.4.0
- *
- * @return int
- */
-function get_header_image_width() {
-	return empty( get_current_header_data()->width )? HEADER_IMAGE_WIDTH : get_current_header_data()->width;
-}
-
-/**
- * Get the header image height.
- *
- * @since 3.4.0
- *
- * @return int
- */
-function get_header_image_height() {
-	return empty( get_current_header_data()->height )? HEADER_IMAGE_HEIGHT : get_current_header_data()->height;
-}
-
-/**
  * Add callbacks for image header display.
  *
- * The parameter $header_callback callback will be required to display the
- * content for the 'wp_head' action. The parameter $admin_header_callback
- * callback will be added to Custom_Image_Header class and that will be added
- * to the 'admin_menu' action.
- *
  * @since 2.1.0
- * @uses Custom_Image_Header Sets up for $admin_header_callback for administration panel display.
+ * @deprecated 3.4.0
+ * @deprecated Use add_theme_support('custom-header', $args)
+ * @see add_theme_support()
  *
  * @param callback $header_callback Call on 'wp_head' action.
  * @param callback $admin_header_callback Call on custom header administration screen.
  * @param callback $admin_image_div_callback Output a custom header image div on the custom header administration screen. Optional.
  */
 function add_custom_image_header( $header_callback, $admin_header_callback, $admin_image_div_callback = '' ) {
-	if ( ! empty( $header_callback ) )
-		add_action('wp_head', $header_callback);
-
-	$support = array( 'callback' => $header_callback );
-	$theme_support = get_theme_support( 'custom-header' );
-	if ( ! empty( $theme_support ) && is_array( $theme_support[ 0 ] ) )
-		$support = array_merge( $theme_support[ 0 ], $support );
-	add_theme_support( 'custom-header',  $support );
-	add_theme_support( 'custom-header-uploads' );
-
-	if ( ! is_admin() )
-		return;
-
-	global $custom_image_header;
-
-	require_once( ABSPATH . 'wp-admin/custom-header.php' );
-	$custom_image_header = new Custom_Image_Header( $admin_header_callback, $admin_image_div_callback );
-	add_action( 'admin_menu', array( &$custom_image_header, 'init' ) );
+	# _deprecated_function( __FUNCTION__, '3.4', 'add_theme_support(\'custom-header\', $args)' );
+	return add_theme_support( 'custom-header', array(
+		'callback' => $header_callback,
+		'admin-header-callback' => $admin_header_callback,
+		'admin-image-div-callback' => $admin_image_div_callback,
+	) );
 }
 
 /**
  * Remove image header support.
  *
  * @since 3.1.0
- * @see add_custom_image_header()
+ * @deprecated 3.4.0
+ * @deprecated Use remove_theme_support('custom-header')
+ * @see remove_theme_support()
  *
  * @return bool Whether support was removed.
  */
 function remove_custom_image_header() {
-	if ( ! current_theme_supports( 'custom-header' ) )
-		return false;
-
-	$callback = get_theme_support( 'custom-header' );
-	remove_action( 'wp_head', $callback[0]['callback'] );
-	_remove_theme_support( 'custom-header' );
-	remove_theme_support( 'custom-header-uploads' );
-
-	if ( is_admin() ) {
-		remove_action( 'admin_menu', array( &$GLOBALS['custom_image_header'], 'init' ) );
-		unset( $GLOBALS['custom_image_header'] );
-	}
-
-	return true;
+	# _deprecated_function( __FUNCTION__, '3.4', 'remove_theme_support(\'custom-header\')' );
+	return remove_theme_support( 'custom-header' );
 }
 
 /**
@@ -1214,9 +1159,7 @@
  * @return string
  */
 function get_background_image() {
-	$default = defined('BACKGROUND_IMAGE') ? BACKGROUND_IMAGE : '';
-
-	return get_theme_mod('background_image', $default);
+	return get_theme_mod('background_image', get_theme_support( 'custom-background', 'default-image' ) );
 }
 
 /**
@@ -1232,14 +1175,11 @@
  * Retrieve value for custom background color.
  *
  * @since 3.0.0
- * @uses BACKGROUND_COLOR
  *
  * @return string
  */
 function get_background_color() {
-	$default = defined('BACKGROUND_COLOR') ? BACKGROUND_COLOR : '';
-
-	return get_theme_mod('background_color', $default);
+	return get_theme_mod('background_color', get_theme_support( 'custom-background', 'default-color' ) );
 }
 
 /**
@@ -1267,21 +1207,12 @@
  * @param callback $admin_image_div_callback Output a custom background image div on the custom background administration screen. Optional.
  */
 function add_custom_background( $header_callback = '', $admin_header_callback = '', $admin_image_div_callback = '' ) {
-	if ( isset( $GLOBALS['custom_background'] ) )
-		return;
-
-	if ( empty( $header_callback ) )
-		$header_callback = '_custom_background_cb';
-
-	add_action( 'wp_head', $header_callback );
-
-	add_theme_support( 'custom-background', array( 'callback' => $header_callback ) );
-
-	if ( ! is_admin() )
-		return;
-	require_once( ABSPATH . 'wp-admin/custom-background.php' );
-	$GLOBALS['custom_background'] = new Custom_Background( $admin_header_callback, $admin_image_div_callback );
-	add_action( 'admin_menu', array( &$GLOBALS['custom_background'], 'init' ) );
+	# _deprecated_function( __FUNCTION__, '3.4', 'add_theme_support(\'custom-background\', $args)' );
+	return add_theme_support( 'custom-background', array(
+		'callback' => $header_callback,
+		'admin-header-callback' => $admin_header_callback,
+		'admin-image-div-callback' => $admin_image_div_callback,
+	) );
 }
 
 /**
@@ -1293,26 +1224,14 @@
  * @return bool Whether support was removed.
  */
 function remove_custom_background() {
-	if ( ! current_theme_supports( 'custom-background' ) )
-		return false;
-
-	$callback = get_theme_support( 'custom-background' );
-	remove_action( 'wp_head', $callback[0]['callback'] );
-	_remove_theme_support( 'custom-background' );
-
-	if ( is_admin() ) {
-		remove_action( 'admin_menu', array( &$GLOBALS['custom_background'], 'init' ) );
-		unset( $GLOBALS['custom_background'] );
-	}
-
-	return true;
+	# _deprecated_function( __FUNCTION__, '3.4', 'remove_theme_support(\'custom-background\')' );
+	return remove_theme_support( 'custom-background' );
 }
 
 /**
  * Default custom background callback.
  *
  * @since 3.0.0
- * @see add_custom_background()
  * @access protected
  */
 function _custom_background_cb() {
@@ -1418,15 +1337,161 @@
 	global $_wp_theme_features;
 
 	if ( func_num_args() == 1 )
-		$_wp_theme_features[$feature] = true;
+		$args = true;
 	else
-		$_wp_theme_features[$feature] = array_slice( func_get_args(), 1 );
+		$args = array_slice( func_get_args(), 1 );
 
-	if ( $feature == 'post-formats' && is_array( $_wp_theme_features[$feature][0] ) )
-		$_wp_theme_features[$feature][0] = array_intersect( $_wp_theme_features[$feature][0], array_keys( get_post_format_slugs() ) );
+	switch ( $feature ) {
+		case 'post-formats' :
+			if ( is_array( $args[0] ) )
+				$args[0] = array_intersect( $args[0], array_keys( get_post_format_slugs() ) );
+			break;
+
+		case 'custom-header-uploads' :
+			return add_theme_support( 'custom-header', array( 'uploads' => true ) );
+			break;
+
+		case 'custom-header' :
+			$defaults = array(
+				'default-image' => '',
+				'random-default' => false,
+				'width' => 0,
+				'height' => 0,
+				'suggested-width' => 0,
+				'suggested-height' => 0,
+				'flex-height' => false,
+				'flex-width' => false,
+				'default-text-color' => '',
+				'header-text' => true,
+				'uploads' => true,
+				'callback' => '',
+				'admin-header-callback' => '',
+				'admin-image-div-callback' => '',
+			);
+
+			// Merge in data from previous add_theme_support() calls.
+			if ( isset( $_wp_theme_features['custom-header'] ) )
+				$defaults = wp_parse_args( $_wp_theme_features['custom-header'][0], $defaults );
+
+			$_args = $args[0];
+			$args[0] = wp_parse_args( $args[0], $defaults );
+			unset( $args[0]['__jit'] );
+
+			// If a constant was defined, use that value. Otherwise, define the constant.
+			// For values based on constants, the first value wins. (A child theme is set up first.)
+			// Once we get to wp_loaded (just-in-time), define any constants we haven't already.
+			// Constants are lame. Don't reference them. This is just for backwards compatibility.
+
+			if ( defined( 'NO_HEADER_TEXT' ) )
+				$args[0]['header-text'] = ! NO_HEADER_TEXT;
+			elseif ( ! empty( $args[0]['header-text'] ) || isset( $_args['__jit'] ) )
+				define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) );
+
+			if ( defined( 'HEADER_IMAGE_WIDTH' ) )
+				$args[0]['width'] = (int) HEADER_IMAGE_WIDTH;
+			elseif ( ! empty( $args[0]['width'] ) || isset( $_args['__jit'] ) )
+				define( 'HEADER_IMAGE_WIDTH', (int) $args[0]['width'] );
+
+			if ( defined( 'HEADER_IMAGE_HEIGHT' ) )
+				$args[0]['height'] = (int) HEADER_IMAGE_HEIGHT;
+			elseif ( ! empty( $args[0]['height'] ) || isset( $_args['__jit'] ) )
+				define( 'HEADER_IMAGE_HEIGHT', (int) $args[0]['height'] );
+
+			if ( defined( 'HEADER_TEXTCOLOR' ) )
+				$args[0]['default-text-color'] = HEADER_TEXTCOLOR;
+			elseif ( $args[0]['default-text-color'] || isset( $_args['__jit'] ) )
+				define( 'HEADER_TEXTCOLOR', $args[0]['default-text-color'] );
+
+			if ( defined( 'HEADER_IMAGE' ) )
+				$args[0]['default-image'] = HEADER_IMAGE;
+
+			if ( ! empty( $args[0]['default-image'] ) )
+				$args[0]['random-default'] = false;
+
+			if ( ! defined( 'HEADER_IMAGE' )
+				&& ( isset( $_args['default-image'] ) || isset( $_args['random-default'] ) || isset( $_args['__jit'] ) ) )
+					define( 'HEADER_IMAGE', $args[0]['default-image'] );
+
+			if ( ! empty( $args[0]['width'] ) )
+				$args[0]['flex-width'] = $args[0]['suggested-width'] = $args[0]['max-width'] = false;
+
+			if ( ! empty( $args[0]['height'] ) )
+				$args[0]['flex-height'] = $args[0]['suggested-height'] = false;
+
+			break;
+
+		case 'custom-background' :
+			$defaults = array(
+				'default-image' => '',
+				'default-color' => '',
+				'callback' => '',
+				'admin-header-callback' => '',
+				'admin-image-div-callback' => '',
+			);
+			if ( isset( $_wp_theme_features['custom-background'] ) )
+				$defaults = wp_parse_args( $_wp_theme_features['custom-background'][0], $defaults );
+
+			$_args = $args[0];
+			$args[0] = wp_parse_args( $args[0], $defaults );
+
+			if ( defined( 'BACKGROUND_COLOR' ) )
+				$args[0]['default-color'] = BACKGROUND_COLOR;
+			elseif ( $args[0]['default-color'] || isset( $_args['__jit'] ) )
+				define( 'BACKGROUND_COLOR', $args[0]['default-color'] );
+
+			if ( defined( 'BACKGROUND_IMAGE' ) )
+				$args[0]['default-image'] = BACKGROUND_HEADER;
+			elseif ( $args[0]['default-image'] || isset( $_args['__jit'] ) )
+				define( 'BACKGROUND_IMAGE', $args[0]['default-image'] );
+
+			if ( empty( $args[0]['callback'] ) )
+				$args[0]['callback'] = '_custom_background_cb';
+
+			break;
+	}
+
+	$_wp_theme_features[ $feature ] = $args;
 }
 
 /**
+ * Registers the internal custom header and background routines.
+ *
+ * @since 3.4.0
+ * @access private
+ */
+function _custom_header_background_just_in_time() {
+	global $custom_image_header, $custom_background;
+
+	if ( current_theme_supports( 'custom-header' ) ) {
+		// In case any constants were defined after an add_custom_image_header() call, re-run.
+		add_theme_support( 'custom-header', array( '__jit' => true ) );
+
+		$args = get_theme_support( 'custom-header' );
+		if ( $args[0]['callback'] )
+			add_action( 'wp_head', $args[0]['callback'] );
+
+		if ( is_admin() ) {
+			require_once( ABSPATH . 'wp-admin/custom-header.php' );
+			$custom_image_header = new Custom_Image_Header( $args[0]['admin-header-callback'], $args[0]['admin-image-div-callback'] );
+		}
+	}
+
+	if ( current_theme_supports( 'custom-background' ) ) {
+		// In case any constants were defined after an add_custom_background() call, re-run.
+		add_theme_support( 'custom-background', array( '__jit' => true ) );
+
+		$args = get_theme_support( 'custom-background' );
+		add_action( 'wp_head', $args[0]['callback'] );
+
+		if ( is_admin() ) {
+			require_once( ABSPATH . 'wp-admin/custom-background.php' );
+			$custom_background = new Custom_Background( $args[0]['admin-header-callback'], $args[0]['admin-image-div-callback'] );
+		}
+	}		
+}
+add_action( 'wp_loaded', '_custom_header_background_just_in_time' );
+
+/**
  * Gets the theme support arguments passed when registering that support
  *
  * @since 3.1
@@ -1435,10 +1500,24 @@
  */
 function get_theme_support( $feature ) {
 	global $_wp_theme_features;
-	if ( !isset( $_wp_theme_features[$feature] ) )
+	if ( ! isset( $_wp_theme_features[ $feature ] ) )
 		return false;
-	else
-		return $_wp_theme_features[$feature];
+
+	if ( func_num_args() <= 1 )
+		return $_wp_theme_features[ $feature ];
+
+	$args = array_slice( func_get_args(), 1 );
+	switch ( $feature ) {
+		case 'custom-header' :
+		case 'custom-background' :
+			if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) )
+				return $_wp_theme_features[ $feature ][0][ $args[0] ];
+			return false;
+			break;
+		default :
+			return $_wp_theme_features[ $feature ];
+			break;
+	}
 }
 
 /**
@@ -1454,8 +1533,9 @@
  */
 function remove_theme_support( $feature ) {
 	// Blacklist: for internal registrations not used directly by themes.
-	if ( in_array( $feature, array( 'custom-background', 'custom-header', 'editor-style', 'widgets', 'menus' ) ) )
+	if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ) ) )
 		return false;
+
 	return _remove_theme_support( $feature );
 }
 
@@ -1468,9 +1548,33 @@
 function _remove_theme_support( $feature ) {
 	global $_wp_theme_features;
 
-	if ( ! isset( $_wp_theme_features[$feature] ) )
+	switch ( $feature ) {
+		case 'custom-header-uploads' :
+			if ( ! isset( $_wp_theme_features['custom-header'] ) )
+				return false;
+			add_theme_support( 'custom-header', array( 'uploads' => false ) );
+			return; // Do not continue - custom-header-uploads no longer exists.
+	}
+
+	if ( ! isset( $_wp_theme_features[ $feature ] ) )
 		return false;
-	unset( $_wp_theme_features[$feature] );
+
+	switch ( $feature ) {
+		case 'custom-header' :
+			$support = get_theme_support( 'custom-header' );
+			if ( $support[0]['callback'] )
+				remove_action( 'wp_head', $support[0]['callback'] );
+			unset( $GLOBALS['custom_image_header'] );
+			break;
+
+		case 'custom-header' :
+			$support = get_theme_support( 'custom-background' );
+			remove_action( 'wp_head', $support[0]['callback'] );
+			unset( $GLOBALS['custom_background'] );
+			break;
+	}
+
+	unset( $_wp_theme_features[ $feature ] );
 	return true;
 }
 
@@ -1484,6 +1588,9 @@
 function current_theme_supports( $feature ) {
 	global $_wp_theme_features;
 
+	if ( 'custom-header-uploads' == $feature )
+		return current_theme_supports( 'custom-header', 'uploads' );
+
 	if ( !isset( $_wp_theme_features[$feature] ) )
 		return false;
 
Index: wp-admin/custom-header.php
===================================================================
--- wp-admin/custom-header.php	(revision 20206)
+++ wp-admin/custom-header.php	(working copy)
@@ -71,9 +71,18 @@
 	function __construct($admin_header_callback, $admin_image_div_callback = '') {
 		$this->admin_header_callback = $admin_header_callback;
 		$this->admin_image_div_callback = $admin_image_div_callback;
+
+		add_action( 'admin_menu', array( $this, 'init' ) );
 	}
 
 	/**
+	 * Destructor - Remove admin menu hook when theme support is removed.
+	 */
+	function __destruct() {
+		remove_action( 'admin_menu', array( $this, 'init' ) );
+	}
+
+	/**
 	 * Set up the hooks for the Custom Header admin page.
 	 *
 	 * @since 2.1.0
@@ -140,7 +149,7 @@
 	function js_includes() {
 		$step = $this->step();
 
-		if ( ( 1 == $step || 3 == $step ) && $this->header_text() )
+		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
 			wp_enqueue_script('farbtastic');
 		elseif ( 2 == $step )
 			wp_enqueue_script('imgareaselect');
@@ -154,25 +163,13 @@
 	function css_includes() {
 		$step = $this->step();
 
-		if ( ( 1 == $step || 3 == $step ) && $this->header_text() )
+		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
 			wp_enqueue_style('farbtastic');
 		elseif ( 2 == $step )
 			wp_enqueue_style('imgareaselect');
 	}
 
 	/**
-	 * Check if header text is allowed
-	 *
-	 * @since 3.0.0
-	 */
-	function header_text() {
-		if ( defined( 'NO_HEADER_TEXT' ) && NO_HEADER_TEXT )
-			return false;
-
-		return true;
-	}
-
-	/**
 	 * Execute custom header modification.
 	 *
 	 * @since 2.6.0
@@ -189,7 +186,7 @@
 		if ( isset( $_POST['resetheader'] ) ) {
 			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );
 			$this->process_default_headers();
-			$default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : '';
+			$default = get_theme_support( 'custom-header', 'default-image' );
 			$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
 			foreach ( $this->default_headers as $header => $details ) {
 				if ( $details['url'] == $default ) {
@@ -199,9 +196,9 @@
 			}
 			set_theme_mod( 'header_image', $default );
 			if ( empty( $default_data['width'] ) )
-				$default_data['width'] = HEADER_IMAGE_WIDTH;
+				$default_data['width'] = get_theme_support( 'custom-header', 'width' );
 			if ( empty( $default_data['height'] ) )
-				$default_data['height'] = HEADER_IMAGE_HEIGHT;
+				$default_data['height'] = get_theme_support( 'custom-header', 'height' );
 			set_theme_mod( 'header_image_data', (object) $default_data );
 			return;
 		}
@@ -245,9 +242,9 @@
 				} elseif ( isset( $this->default_headers[$_POST['default-header']] ) ) {
 					set_theme_mod( 'header_image', esc_url( $this->default_headers[$_POST['default-header']]['url'] ) );
 					if ( empty( $this->default_headers[$_POST['default-header']]['width'] ) )
-						$this->default_headers[$_POST['default-header']]['width'] = HEADER_IMAGE_WIDTH;
+						$this->default_headers[$_POST['default-header']]['width'] = get_theme_support( 'custom-header', 'width' );
 					if ( empty( $this->default_headers[$_POST['default-header']]['height'] ) )
-						$this->default_headers[$_POST['default-header']]['height'] = HEADER_IMAGE_HEIGHT;
+						$this->default_headers[$_POST['default-header']]['height'] = get_theme_support( 'custom-header', 'height' );
 					set_theme_mod( 'header_image_data', (object) $this->default_headers[$_POST['default-header']] );
 				}
 			}
@@ -325,7 +322,7 @@
 	 */
 	function js() {
 		$step = $this->step();
-		if ( ( 1 == $step || 3 == $step ) && $this->header_text() )
+		if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) )
 			$this->js_1();
 		elseif ( 2 == $step )
 			$this->js_2();
@@ -341,7 +338,7 @@
 /* <![CDATA[ */
 	var text_objects = ['#name', '#desc', '#text-color-row'];
 	var farbtastic;
-	var default_color = '#<?php echo HEADER_TEXTCOLOR; ?>';
+	var default_color = '#<?php echo get_theme_support( 'custom-header', 'default-text-color' ); ?>';
 	var old_color = null;
 
 	function pickColor(color) {
@@ -411,11 +408,11 @@
 		});
 
 		farbtastic = jQuery.farbtastic('#color-picker', function(color) { pickColor(color); });
-		<?php if ( $color = get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) ) { ?>
+		<?php if ( $color = get_header_textcolor() ) { ?>
 		pickColor('#<?php echo $color; ?>');
 		<?php } ?>
 
-		<?php if ( 'blank' == get_theme_mod( 'header_textcolor', HEADER_TEXTCOLOR ) || '' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || ! $this->header_text() ) { ?>
+		<?php if ( 'blank' == $color || '' == $color || ! current_theme_supports( 'custom-header', 'header-text' ) ) { ?>
 		toggle_text();
 		<?php } ?>
 	});
@@ -441,13 +438,10 @@
 
 	jQuery(document).ready(function() {
 		<?php
-		$xinit = HEADER_IMAGE_WIDTH;
-		$yinit = HEADER_IMAGE_HEIGHT;
-		$header_support = get_theme_support( 'custom-header' );
-		if ( !empty( $header_support[ 0 ][ 'suggested-width' ] ) )
-			$xinit = $header_support[ 0 ][ 'suggested-width' ];
-		if ( !empty( $header_support[ 0 ][ 'suggested-height' ] ) )
-			$yinit = $header_support[ 0 ][ 'suggested-height' ];
+		if ( ! $xinit = get_theme_support( 'custom-header', 'suggested-width' ) )
+			$xinit = get_theme_support( 'custom-header', 'width' );
+		if ( ! $yinit = get_theme_support( 'custom-header', 'suggested-height' ) )
+			$yinit = get_theme_support( 'custom-header', 'height' );
 		?>
 		var xinit = <?php echo absint( $xinit ); ?>;
 		var yinit = <?php echo absint( $yinit ); ?>;
@@ -481,12 +475,12 @@
 			}
 			if ( ! current_theme_supports( 'custom-header', 'flex-height' ) ) {
 			?>
-			maxHeight: <?php echo HEADER_IMAGE_HEIGHT; ?>,
+			maxHeight: <?php echo get_theme_support( 'custom-header', 'height' ); ?>,
 			<?php
 			}
 			if ( ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
 			?>
-			maxWidth: <?php echo HEADER_IMAGE_WIDTH; ?>,
+			maxWidth: <?php echo get_theme_support( 'custom-header', 'width' ); ?>,
 			<?php
 			}
 			?>
@@ -531,17 +525,18 @@
 
 <tr valign="top">
 <th scope="row"><?php _e( 'Preview' ); ?></th>
-<td >
+<td>
 	<?php if ( $this->admin_image_div_callback ) {
 	  call_user_func( $this->admin_image_div_callback );
 	} else {
 	?>
-	<div id="headimg" style="background-image:url(<?php esc_url ( header_image() ) ?>);max-width:<?php echo get_header_image_width(); ?>px;height:<?php echo get_header_image_height(); ?>px;">
+	<div id="headimg" style="background-image:url(<?php esc_url ( header_image() ) ?>);max-width:<?php echo get_custom_header()->width; ?>px;height:<?php echo get_custom_header()->height; ?>px;">
 		<?php
-		if ( 'blank' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || '' == get_theme_mod('header_textcolor', HEADER_TEXTCOLOR) || ! $this->header_text() )
+		$color = get_header_textcolor();
+		if ( 'blank' == $color || '' == $color || ! current_theme_supports( 'custom-header', 'header-text' ) )
 			$style = ' style="display:none;"';
 		else
-			$style = ' style="color:#' . get_theme_mod( 'header_textcolor', HEADER_TEXTCOLOR ) . ';"';
+			$style = ' style="color:#' . $color . ';"';
 		?>
 		<h1><a id="name"<?php echo $style; ?> onclick="return false;" href="<?php bloginfo('url'); ?>"><?php bloginfo( 'name' ); ?></a></h1>
 		<div id="desc"<?php echo $style; ?>><?php bloginfo( 'description' ); ?></div>
@@ -556,20 +551,19 @@
 	<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
 	if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
-		printf( __( 'Images of exactly <strong>%1$d &times; %2$d pixels</strong> will be used as-is.' ) . '<br />', HEADER_IMAGE_WIDTH, HEADER_IMAGE_HEIGHT );
+		printf( __( 'Images of exactly <strong>%1$d &times; %2$d pixels</strong> will be used as-is.' ) . '<br />', get_theme_support( 'custom-header', 'width' ), get_theme_support( 'custom-header', 'height' ) );
 	} elseif ( current_theme_supports( 'custom-header', 'flex-height' ) ) {
 		if ( ! current_theme_supports( 'custom-header', 'flex-width' ) )
-			printf( __( 'Images should be at least <strong>%1$d pixels</strong> wide.' ) . '<br />', HEADER_IMAGE_WIDTH );
+			printf( __( 'Images should be at least <strong>%1$d pixels</strong> wide.' ) . '<br />', get_theme_support( 'custom-header', 'width' ) );
 	} elseif ( current_theme_supports( 'custom-header', 'flex-width' ) ) {
 		if ( ! current_theme_supports( 'custom-header', 'flex-height' ) )
-			printf( __( 'Images should be at least <strong>%1$d pixels</strong> tall.' ) . '<br />', HEADER_IMAGE_HEIGHT );
+			printf( __( 'Images should be at least <strong>%1$d pixels</strong> tall.' ) . '<br />', get_theme_support( 'custom-header', 'height' ) );
 	}
 	if ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) {
-		$header_support = get_theme_support( 'custom-header' );
-		if ( !empty( $header_support[ 0 ][ 'suggested-width' ] ) )
-			printf( __( 'Suggested width is <strong>%1$d pixels</strong>.' ) . '<br />', absint( $header_support[ 0 ][ 'suggested-width' ] ) );
-		if ( !empty( $header_support[ 0 ][ 'suggested-height' ] ) )
-			printf( __( 'Suggested height is <strong>%1$d pixels</strong>.' ) . '<br />', absint( $header_support[ 0 ][ 'suggested-height' ] ) );
+		if ( current_theme_supports( 'custom-header', 'suggested-width' ) )
+			printf( __( 'Suggested width is <strong>%1$d pixels</strong>.' ) . '<br />', get_theme_support( 'custom-header', 'suggested-width' ) );
+		if ( current_theme_supports( 'custom-header', 'suggested-height' ) )
+			printf( __( 'Suggested height is <strong>%1$d pixels</strong>.' ) . '<br />', get_theme_support( 'custom-header', 'suggested-height' ) );
 	}
 	?></p>
 	<form enctype="multipart/form-data" id="upload-form" method="post" action="<?php echo esc_attr( add_query_arg( 'step', 2 ) ) ?>">
@@ -626,7 +620,7 @@
 </tr>
 	<?php endif;
 
-	if ( defined( 'HEADER_IMAGE' ) && '' != HEADER_IMAGE ) : ?>
+	if ( current_theme_supports( 'custom-header', 'default-image' ) ) : ?>
 <tr valign="top">
 <th scope="row"><?php _e( 'Reset Image' ); ?></th>
 <td>
@@ -637,16 +631,22 @@
 	<?php endif; ?>
 </tbody>
 </table>
-	<?php if ( $this->header_text() ) : ?>
+	<?php if ( current_theme_supports( 'custom-header', 'header-text' ) ) : ?>
 <table class="form-table">
 <tbody>
 <tr valign="top" class="hide-if-no-js">
 <th scope="row"><?php _e( 'Display Text' ); ?></th>
 <td>
 	<p>
-	<?php $hidetext = get_theme_mod( 'header_textcolor', HEADER_TEXTCOLOR ); ?>
-	<label><input type="radio" value="1" name="hidetext" id="hidetext"<?php checked( ( 'blank' == $hidetext || empty( $hidetext ) )  ? true : false ); ?> /> <?php _e( 'No' ); ?></label>
-	<label><input type="radio" value="0" name="hidetext" id="showtext"<?php checked( ( 'blank' == $hidetext || empty( $hidetext ) ) ? false : true ); ?> /> <?php _e( 'Yes' ); ?></label>
+	<?php
+		$show_text = get_header_textcolor();
+		if ( 'blank' == $show_text )
+			$show_text = false;
+		else
+			$show_text = (bool) $show_text;
+	?>
+	<label><input type="radio" value="1" name="hidetext" id="hidetext"<?php checked( ! $show_text ); ?> /> <?php _e( 'No' ); ?></label>
+	<label><input type="radio" value="0" name="hidetext" id="showtext"<?php checked( $show_text ); ?> /> <?php _e( 'Yes' ); ?></label>
 	</p>
 </td>
 </tr>
@@ -655,7 +655,7 @@
 <th scope="row"><?php _e( 'Text Color' ); ?></th>
 <td>
 	<p>
-		<input type="text" name="text-color" id="text-color" value="#<?php echo esc_attr( get_theme_mod( 'header_textcolor', HEADER_TEXTCOLOR ) ); ?>" />
+		<input type="text" name="text-color" id="text-color" value="#<?php echo esc_attr( get_header_textcolor() ); ?>" />
 		<span class="description hide-if-js"><?php _e( 'If you want to hide header text, add <strong>#blank</strong> as text color.' );?></span>
 		<input type="button" class="button hide-if-no-js" value="<?php esc_attr_e( 'Select a Color' ); ?>" id="pickcolor" />
 	</p>
@@ -663,7 +663,7 @@
 </td>
 </tr>
 
-	<?php if ( defined('HEADER_TEXTCOLOR') && get_theme_mod('header_textcolor') ) { ?>
+	<?php if ( current_theme_supports( 'custom-header', 'default-text-color' ) && get_theme_mod( 'header_textcolor' ) ) { ?>
 <tr valign="top">
 <th scope="row"><?php _e('Reset Text Color'); ?></th>
 <td>
@@ -722,19 +722,19 @@
 
 		list($width, $height, $type, $attr) = getimagesize( $file );
 
-		$header_support = get_theme_support( 'custom-header' );
 		$max_width = 0;
 		// For flex, limit size of image displayed to 1500px unless theme says otherwise
 		if ( current_theme_supports( 'custom-header', 'flex-width' ) )
 			$max_width = 1500;
 
-		if ( !empty( $header_support[ 0 ][ 'max-width' ] ) )
-			$max_width = max( $max_width, absint( $header_support[ 0 ][ 'max-width' ] ) );
+		if ( current_theme_supports( 'custom-header', 'max-width' ) )
+			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
+		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
 
-		if ( defined( 'HEADER_IMAGE_WIDTH' ) )
-			$max_width = max( $max_width, HEADER_IMAGE_WIDTH );
 		// If flexible height isn't supported and the image is the exact right size
-		if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) && $width == HEADER_IMAGE_WIDTH && $height == HEADER_IMAGE_HEIGHT ) {
+		if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' )
+			&& $width == get_theme_support( 'custom-header', 'width' ) && $height == get_theme_support( 'custom-header', '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' ) );
@@ -791,8 +791,9 @@
 	 * @since 2.1.0
 	 */
 	function step_3() {
-		check_admin_referer('custom-header-crop-image');
-		if ( ! current_theme_supports( 'custom-header-uploads' ) )
+		check_admin_referer( 'custom-header-crop-image' );
+
+		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
 			wp_die( __( 'Cheatin&#8217; uh?' ) );
 
 		if ( $_POST['oitar'] > 1 ) {
@@ -805,31 +806,29 @@
 		$attachment_id = absint( $_POST['attachment_id'] );
 		$original = get_attached_file($attachment_id);
 
-		$header_support = get_theme_support( 'custom-header' );
+
 		$max_width = 0;
 		// For flex, limit size of image displayed to 1500px unless theme says otherwise
 		if ( current_theme_supports( 'custom-header', 'flex-width' ) )
 			$max_width = 1500;
 
-		if ( !empty( $header_support[ 0 ][ 'max-width' ] ) )
-			$max_width = max( $max_width, absint( $header_support[ 0 ][ 'max-width' ] ) );
+		if ( current_theme_supports( 'custom-header', 'max-width' ) )
+			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
+		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
 
-		if ( defined( 'HEADER_IMAGE_WIDTH' ) )
-			$max_width = max( $max_width, HEADER_IMAGE_WIDTH );
-
 		if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
 			$dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
 		elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
 			$dst_height = absint( $_POST['height'] );
 		else
-			$dst_height = HEADER_IMAGE_HEIGHT;
+			$dst_height = get_theme_support( 'custom-header', 'height' );
 
 		if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
 			$dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
 		elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
 			$dst_width = absint( $_POST['width'] );
 		else
-			$dst_width = HEADER_IMAGE_WIDTH;
+			$dst_width = get_theme_support( 'custom-header', 'width' );
 
 		$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
 		if ( is_wp_error( $cropped ) )
@@ -894,7 +893,7 @@
 		if ( ! current_user_can('edit_theme_options') )
 			wp_die(__('You do not have permission to customize headers.'));
 		$step = $this->step();
-		if ( 1 == $step )
+		if ( 1 == $step || ! $_POST )
 			$this->step_1();
 		elseif ( 2 == $step )
 			$this->step_2();
Index: wp-admin/custom-background.php
===================================================================
--- wp-admin/custom-background.php	(revision 20186)
+++ wp-admin/custom-background.php	(working copy)
@@ -53,9 +53,18 @@
 	function __construct($admin_header_callback = '', $admin_image_div_callback = '') {
 		$this->admin_header_callback = $admin_header_callback;
 		$this->admin_image_div_callback = $admin_image_div_callback;
+
+		add_action( 'admin_menu', array( $this, 'init' ) );
 	}
 
 	/**
+	 * Destructor - Remove admin menu hook when theme support is removed.
+	 */
+	function __destruct() {
+		remove_action( 'admin_menu', array( $this, 'init' ) );
+	}
+
+	/**
 	 * Set up the hooks for the Custom Background admin page.
 	 *
 	 * @since 3.0.0
@@ -226,7 +235,7 @@
 </tr>
 <?php endif; ?>
 
-<?php if ( defined( 'BACKGROUND_IMAGE' ) ) : // Show only if a default background image exists ?>
+<?php if ( get_theme_support( 'custom-background', 'default-image' ) ) : ?>
 <tr valign="top">
 <th scope="row"><?php _e('Restore Original Image'); ?></th>
 <td>
