diff -rupN postgis-old/raster/rt_core/rt_api.c postgis-new/raster/rt_core/rt_api.c
--- postgis-old/raster/rt_core/rt_api.c	2011-05-15 09:52:32.000000000 -0700
+++ postgis-new/raster/rt_core/rt_api.c	2011-05-15 10:01:48.000000000 -0700
@@ -3850,3 +3850,54 @@ int32_t rt_raster_copy_band(rt_raster to
     return rt_raster_add_band(torast, newband, toindex);
 }
 
+/**
+ * Construct a new rt_raster from an existing rt_raster and an array
+ * of band numbers
+ *
+ * @param raster : the source raster
+ * @param bandNums : array of band numbers to extract from source raster
+ *                   and add to the new raster (0 based)
+ * @param count : number of elements in bandNums
+ *
+ * @return a new rt_raster or 0 on error
+ */
+rt_raster
+rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count) {
+	rt_raster rast = NULL;
+	int i = 0;
+	int idx;
+	int32_t flag;
+
+	assert(NULL != raster);
+	assert(NULL != bandNums);
+
+	RASTER_DEBUGF(3, "rt_raster_from_band: source raster has %d bands",
+		rt_raster_get_num_bands(raster));
+
+	/* create new raster */
+	rast = rt_raster_new(raster->width, raster->height);
+	if (!rast) {
+		rterror("rt_raster_from_band: Out of memory allocating new raster\n");
+		return 0;
+	}
+
+	/* copy bands */
+	for (i = 0; i < count; i++) {
+		idx = bandNums[i];
+		flag = rt_raster_copy_band(rast, raster, idx, i);
+
+		if (flag < 0) {
+			rterror("rt_raster_from_band: Unable to copy band\n");
+			rt_raster_destroy(rast);
+			return 0;
+		}
+
+		RASTER_DEBUGF(3, "rt_raster_from_band: band created at index %d",
+			flag);
+	}
+
+	RASTER_DEBUGF(3, "rt_raster_from_band: new raster has %d bands",
+		rt_raster_get_num_bands(rast));
+	return rast;
+}
+
diff -rupN postgis-old/raster/rt_core/rt_api.h postgis-new/raster/rt_core/rt_api.h
--- postgis-old/raster/rt_core/rt_api.h	2011-05-15 09:52:32.000000000 -0700
+++ postgis-new/raster/rt_core/rt_api.h	2011-05-15 10:01:44.000000000 -0700
@@ -757,6 +757,21 @@ int rt_raster_has_no_band(rt_raster rast
 int32_t rt_raster_copy_band(rt_raster torast,
         rt_raster fromrast, int fromindex, int toindex);
 
+/**
+ * Construct a new rt_raster from an existing rt_raster and an array
+ * of band numbers
+ *
+ * @param raster : the source raster
+ * @param bandNums : array of band numbers to extract from source raster
+ *                   and add to the new raster (0 based)
+ * @param count : number of elements in bandNums
+ *
+ * @return a new rt_raster or 0 on error
+ */
+rt_raster rt_raster_from_band(rt_raster raster, uint32_t *bandNums,
+	int count);
+
+
 /*- utilities -------------------------------------------------------*/
 
 /*
diff -rupN postgis-old/raster/rt_pg/rt_pg.c postgis-new/raster/rt_pg/rt_pg.c
--- postgis-old/raster/rt_pg/rt_pg.c	2011-05-15 09:52:32.000000000 -0700
+++ postgis-new/raster/rt_pg/rt_pg.c	2011-05-15 10:01:54.000000000 -0700
@@ -49,6 +49,10 @@
 #include "rt_api.h"
 #include "../raster_config.h"
 
+#include <utils/lsyscache.h> /* for get_typlenbyvalalign */
+#include <utils/array.h> /* for ArrayType */
+#include <catalog/pg_type.h> /* for INT2OID, INT4OID, FLOAT4OID, FLOAT8OID and TEXTOID */
+
 #define POSTGIS_RASTER_WARN_ON_TRUNCATION
 
 /*
@@ -180,6 +184,9 @@ Datum RASTER_copyband(PG_FUNCTION_ARGS);
 /* Raster analysis */
 Datum RASTER_mapAlgebra(PG_FUNCTION_ARGS);
 
+/* create new raster from existing raster's bands */
+Datum RASTER_band(PG_FUNCTION_ARGS);
+
 
 /* Replace function taken from
  * http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3
@@ -2617,6 +2624,127 @@ Datum RASTER_mapAlgebra(PG_FUNCTION_ARGS
     PG_RETURN_POINTER(pgraster);
 }
 
+/**
+ * Return new raster from selected bands of existing raster through ST_Band.
+ * second argument is an array of band numbers (1 based)
+ */
+PG_FUNCTION_INFO_V1(RASTER_band);
+Datum RASTER_band(PG_FUNCTION_ARGS)
+{
+	rt_pgraster *pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+	rt_pgraster *pgrast;
+	rt_raster raster;
+	rt_raster rast;
+
+	bool skip = FALSE;
+	ArrayType *array;
+	Oid etype;
+	Datum *e;
+	bool *nulls;
+	int16 typlen;
+	bool typbyval;
+	char typalign;
+	int ndims = 1;
+	int *dims;
+	int *lbs;
+
+	uint32_t *bandNums;
+	uint32 idx = 0;
+	int n;
+	int i = 0;
+	int j = 0;
+
+	raster = rt_raster_deserialize(pgraster);
+	if (!raster) {
+		elog(ERROR, "RASTER_band: Could not deserialize raster");
+		PG_RETURN_NULL();
+	}
+
+	/* process bandNums */
+	if (PG_ARGISNULL(1)) {
+		elog(NOTICE, "Band number(s) not provided.  Returning original raster");
+		skip = TRUE;
+	}
+	do {
+		if (skip) break;
+
+		array = PG_GETARG_ARRAYTYPE_P(1);
+		etype = ARR_ELEMTYPE(array);
+		get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
+
+		switch (etype) {
+			case INT2OID:
+			case INT4OID:
+				break;
+			default:
+				elog(ERROR, "RASTER_band: Invalid data type for band number(s)");
+				rt_raster_destroy(raster);
+				PG_RETURN_NULL();
+				break;
+		}
+
+		ndims = ARR_NDIM(array);
+		dims = ARR_DIMS(array);
+		lbs = ARR_LBOUND(array);
+
+		deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
+			&nulls, &n);
+
+		bandNums = (uint32_t *) palloc(sizeof(uint32_t) * n);
+		for (i = 0, j = 0; i < n; i++) {
+			if (nulls[i]) continue;
+
+			switch (etype) {
+				case INT2OID:
+					idx = (uint32_t) DatumGetInt16(e[i]);
+					break;
+				case INT4OID:
+					idx = (uint32_t) DatumGetInt32(e[i]);
+					break;
+			}
+
+			POSTGIS_RT_DEBUGF(3, "band idx (before): %d", idx);
+			if (idx > pgraster->numBands || idx < 1) {
+        elog(NOTICE, "Invalid band index (must use 1-based). Returning original raster");
+				pfree(bandNums);
+				skip = TRUE;
+			}
+			if (skip) break;
+
+			bandNums[j] = idx - 1;
+			POSTGIS_RT_DEBUGF(3, "bandNums[%d] = %d", j, bandNums[j]);
+			j++;
+		}
+
+		if (skip || j < 1) {
+			pfree(bandNums);
+			skip = TRUE;
+		}
+	}
+	while (0);
+
+	if (!skip) {
+		rast = rt_raster_from_band(raster, bandNums, j);
+		pfree(bandNums);
+		rt_raster_destroy(raster);
+		if (!rast) {
+			elog(ERROR, "RASTER_band: Could not create new raster");
+			PG_RETURN_NULL();
+		}
+
+		pgrast = rt_raster_serialize(rast);
+	}
+	else {
+		pgrast = pgraster;
+	}
+
+	if (!pgrast)
+		PG_RETURN_NULL();
+
+	SET_VARSIZE(pgrast, pgrast->size);
+	PG_RETURN_POINTER(pgrast);
+}
+
 /* ---------------------------------------------------------------- */
 /*  Memory allocation / error reporting hooks                       */
 /* ---------------------------------------------------------------- */
diff -rupN postgis-old/raster/rt_pg/rtpostgis.sql.in.c postgis-new/raster/rt_pg/rtpostgis.sql.in.c
--- postgis-old/raster/rt_pg/rtpostgis.sql.in.c	2011-05-15 09:52:32.000000000 -0700
+++ postgis-new/raster/rt_pg/rtpostgis.sql.in.c	2011-05-15 10:01:57.000000000 -0700
@@ -229,6 +229,34 @@ CREATE OR REPLACE FUNCTION st_addband(to
     LANGUAGE 'SQL' IMMUTABLE STRICT;
 
 -----------------------------------------------------------------------
+-- Constructor ST_Band
+-----------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION st_band(rast raster, nbands int[])
+	RETURNS RASTER
+	AS 'MODULE_PATHNAME', 'RASTER_band'
+	LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster, nband int)
+	RETURNS RASTER
+	AS $$ SELECT st_band($1, ARRAY[$2]) $$
+	LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster, nbands text)
+	RETURNS RASTER
+	AS $$ SELECT st_band($1, regexp_split_to_array(regexp_replace($2, '[[:space:]]', '', 'g'), ',')::int[]) $$
+	LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster, nbands text, delimiter char)
+	RETURNS RASTER
+	AS $$ SELECT st_band($1, regexp_split_to_array(regexp_replace($2, '[[:space:]]', '', 'g'), $3)::int[]) $$
+	LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION st_band(rast raster)
+	RETURNS RASTER
+	AS $$ SELECT st_band($1, ARRAY[1]) $$
+	LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+-----------------------------------------------------------------------
 -- MapAlgebra
 -----------------------------------------------------------------------
 -- This function can not be STRICT, because nodatavalueexpr can be NULL (could be just '' though)
diff -rupN postgis-old/raster/test/core/testapi.c postgis-new/raster/test/core/testapi.c
--- postgis-old/raster/test/core/testapi.c	2011-05-15 09:52:32.000000000 -0700
+++ postgis-new/raster/test/core/testapi.c	2011-05-15 10:01:59.000000000 -0700
@@ -972,6 +972,21 @@ static void testBandHasNoData(rt_band ba
     CHECK_EQUALS(flag, 1);
 }
 
+static void testRasterFromBand(rt_raster raster) {
+	uint32_t bandNums[] = {1,3};
+	int lenBandNums = 2;
+	rt_raster rast;
+
+	rast = rt_raster_from_band(raster, bandNums, lenBandNums);
+	assert(rast);
+
+	CHECK(rast);
+	CHECK(!rt_raster_is_empty(rast));
+	CHECK(!rt_raster_has_no_band(rast, 1));
+
+	rt_raster_destroy(rast);
+}
+
 int
 main()
 {
@@ -1278,6 +1293,11 @@ main()
     printf("Testing band hasnodata flag\n");
     testBandHasNoData(band_64BF);
 
+		printf("Testing rt_raster_from_band\n");
+		testRasterFromBand(raster);
+		printf("Successfully tested rt_raster_from_band\n");
+
+
     deepRelease(raster);
 
     return EXIT_SUCCESS;
diff -rupN postgis-old/raster/test/regress/Makefile.in postgis-new/raster/test/regress/Makefile.in
--- postgis-old/raster/test/regress/Makefile.in	2011-05-15 09:52:32.000000000 -0700
+++ postgis-new/raster/test/regress/Makefile.in	2011-05-15 10:02:03.000000000 -0700
@@ -41,6 +41,7 @@ TEST_FUNC = \
 	create_rt_box2d_test.sql \
 	rt_box2d.sql \
 	rt_addband.sql \
+	rt_band.sql \
 	$(NULL)
 
 TEST_PROPS = \
diff -rupN postgis-old/raster/test/regress/rt_band.sql postgis-new/raster/test/regress/rt_band.sql
--- postgis-old/raster/test/regress/rt_band.sql	1969-12-31 16:00:00.000000000 -0800
+++ postgis-new/raster/test/regress/rt_band.sql	2011-05-15 10:02:26.000000000 -0700
@@ -0,0 +1,256 @@
+SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 123.4567, NULL), ARRAY[1]), 3, 3);
+SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 1234.567, NULL), 1), 3, 3);
+SELECT ST_Value(ST_Band(ST_AddBand(ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0, -1), 1, '64BF', 1234.567, NULL)), 3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1]
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[2]
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[3]
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		1
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		2
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		3
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		)
+	),
+3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1,3]
+	),
+1, 3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1,3]
+	),
+2, 3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[2,3]
+	),
+1, 3, 3);
+SELECT ST_Value(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1,1]
+	),
+2, 3, 3);
+SELECT ST_NumBands(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1,1,3,3]
+	)
+);
+SELECT ST_NumBands(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1,1,3]
+	)
+);
+SELECT ST_NumBands(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[1,2]
+	)
+);
+SELECT ST_NumBands(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		ARRAY[3]
+	)
+);
+SELECT ST_NumBands(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		),
+		2
+	)
+);
+SELECT ST_NumBands(
+	ST_Band(
+		ST_AddBand(
+			ST_AddBand(
+				ST_AddBand(
+					ST_MakeEmptyRaster(200, 200, 10, 10, 2, 2, 0, 0,-1)
+					, 1, '64BF', 1234.5678, NULL
+				)
+				, '64BF', 987.654321, NULL
+			)
+			, '64BF', 9876.54321, NULL
+		)
+	)
+);
diff -rupN postgis-old/raster/test/regress/rt_band_expected postgis-new/raster/test/regress/rt_band_expected
--- postgis-old/raster/test/regress/rt_band_expected	1969-12-31 16:00:00.000000000 -0800
+++ postgis-new/raster/test/regress/rt_band_expected	2011-05-15 10:02:30.000000000 -0700
@@ -0,0 +1,20 @@
+123.4567
+1234.567
+1234.567
+1234.5678
+987.654321
+9876.54321
+1234.5678
+987.654321
+9876.54321
+1234.5678
+1234.5678
+9876.54321
+987.654321
+1234.5678
+4
+3
+2
+1
+1
+1

