]> granicus.if.org Git - postgis/commitdiff
Added CUnit test suites for raster core. Old raster core regression
authorBborie Park <bkpark at ucdavis.edu>
Thu, 29 Nov 2012 01:21:33 +0000 (01:21 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Thu, 29 Nov 2012 01:21:33 +0000 (01:21 +0000)
tests can still be found in raster/test/core but are no longer run.
Probably should delete before 2.1 is released.
Ticket #173

git-svn-id: http://svn.osgeo.org/postgis/trunk@10749 b70326c6-7e19-0410-871a-916f4a2858ee

18 files changed:
.gitignore
configure.ac
raster/test/Makefile.in
raster/test/core/testapi.c
raster/test/cunit/Makefile.in [new file with mode: 0644]
raster/test/cunit/cu_band_basics.c [new file with mode: 0644]
raster/test/cunit/cu_band_misc.c [new file with mode: 0644]
raster/test/cunit/cu_band_stats.c [new file with mode: 0644]
raster/test/cunit/cu_gdal.c [new file with mode: 0644]
raster/test/cunit/cu_mapalgebra.c [new file with mode: 0644]
raster/test/cunit/cu_pixtype.c [new file with mode: 0644]
raster/test/cunit/cu_raster_basics.c [new file with mode: 0644]
raster/test/cunit/cu_raster_geometry.c [new file with mode: 0644]
raster/test/cunit/cu_raster_misc.c [new file with mode: 0644]
raster/test/cunit/cu_raster_wkb.c [new file with mode: 0644]
raster/test/cunit/cu_spatial_relationship.c [new file with mode: 0644]
raster/test/cunit/cu_tester.c [new file with mode: 0644]
raster/test/cunit/cu_tester.h [new file with mode: 0644]

index 9b69b36576f55d19deff5d205ab9b28cb371fe6e..d2b6c807650ee64004731158b16c3eb701f3e1c8 100644 (file)
@@ -102,6 +102,8 @@ raster/scripts/python/Makefile
 raster/test/core/Makefile
 raster/test/core/testapi
 raster/test/core/testwkb
+raster/test/cunit/Makefile
+raster/test/cunit/cu_tester
 raster/test/Makefile
 raster/test/regress/Makefile
 raster/test/regress/rtpostgis.sql
index d592d22b9bf72096a11105590e9263b6993517b4..b82f636ad5b77d28245b3654d220207f607150bb 100644 (file)
@@ -1068,6 +1068,7 @@ if test "x$with_raster" != "xno"; then
                raster/loader/Makefile \
                raster/test/Makefile \
                raster/test/core/Makefile \
+               raster/test/cunit/Makefile \
                raster/test/regress/Makefile \
                raster/scripts/Makefile \
                raster/scripts/python/Makefile"
index c67fa52a2e1a3ddb4c3378f7088a57c5ea397b88..d947e65f59cebaee2be7a0e734cea4183916b93d 100644 (file)
@@ -13,16 +13,16 @@ RT_CORE=../rt_core
 all: check
 
 core-check:
-       $(MAKE) -C core check
+       $(MAKE) -C cunit check
 
 check: core-check
        $(MAKE) -C regress check
 
 clean:
-       $(MAKE) -C core $@
+       $(MAKE) -C cunit $@
        $(MAKE) -C regress $@
 
 distclean: clean
-       $(MAKE) -C core $@
+       $(MAKE) -C cunit $@
        $(MAKE) -C regress $@
        rm -f Makefile
index a8eeb637fd20bdd0a48ee3646d1e4e59a501e435..fab6447f9a27e2167cf34d5163297850e9a00f81 100644 (file)
@@ -8432,194 +8432,240 @@ main()
 
         rt_raster_set_skews(raster, 0, 0);
     }
+               /* done all above */
 
+               /* done */
                printf("Testing rt_util_gdal_configured... ");
                testGDALConfigured();
                printf("OK\n");
 
+               /* done */
     printf("Testing rt_raster_gdal_polygonize... ");
                testGDALPolygonize();
                printf("OK\n");
 
+               /* done */
     printf("Testing 1BB band... ");
     band_1BB = addBand(raster, PT_1BB, 0, 0);
     testBand1BB(band_1BB);
                printf("OK\n");
 
+               /* done */
     printf("Testing 2BB band... ");
     band_2BUI = addBand(raster, PT_2BUI, 0, 0);
     testBand2BUI(band_2BUI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 4BUI band... ");
     band_4BUI = addBand(raster, PT_4BUI, 0, 0);
     testBand4BUI(band_4BUI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 8BUI band... ");
     band_8BUI = addBand(raster, PT_8BUI, 0, 0);
     testBand8BUI(band_8BUI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 8BSI band... ");
     band_8BSI = addBand(raster, PT_8BSI, 0, 0);
     testBand8BSI(band_8BSI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 16BSI band... ");
     band_16BSI = addBand(raster, PT_16BSI, 0, 0);
     testBand16BSI(band_16BSI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 16BUI band... ");
     band_16BUI = addBand(raster, PT_16BUI, 0, 0);
     testBand16BUI(band_16BUI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 32BUI band... ");
     band_32BUI = addBand(raster, PT_32BUI, 0, 0);
     testBand32BUI(band_32BUI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 32BSI band... ");
     band_32BSI = addBand(raster, PT_32BSI, 0, 0);
     testBand32BSI(band_32BSI);
                printf("OK\n");
 
+               /* done */
     printf("Testing 32BF band... ");
     band_32BF = addBand(raster, PT_32BF, 0, 0);
     testBand32BF(band_32BF);
                printf("OK\n");
 
+               /* done */
     printf("Testing 64BF band... ");
     band_64BF = addBand(raster, PT_64BF, 0, 0);
     testBand64BF(band_64BF);
                printf("OK\n");
 
+               /* done */
     printf("Testing band hasnodata flag... ");
     testBandHasNoData(band_64BF);
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_from_band... ");
                testRasterFromBand();
                printf("OK\n");
 
+               /* done */
                printf("Testing band stats... ");
                testBandStats();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_replace_band... ");
                testRasterReplaceBand();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_band_reclass... ");
                testBandReclass();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_to_gdal... ");
                testRasterToGDAL();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_gdal_drivers... ");
                testGDALDrivers();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_band_get_value_count... ");
                testValueCount();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_from_gdal_dataset... ");
                testGDALToRaster();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_util_compute_skewed_extent... ");
                testComputeSkewedExtent();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_gdal_warp... ");
                testGDALWarp();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_gdal_rasterize... ");
                testGDALRasterize();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_intersects... ");
                testIntersects();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_surface... ");
                testRasterSurface();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_overlaps... ");
                testOverlaps();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_touches... ");
                testTouches();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_contains... ");
                testContains();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_contains_properly... ");
                testContainsProperly();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_covers... ");
                testCovers();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_covered_by... ");
                testCoveredBy();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_within_distance... ");
                testDWithin();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_fully_within_distance... ");
                testDFullyWithin();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_same_alignment... ");
                testAlignment();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_from_two_rasters... ");
                testFromTwoRasters();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_load_offline_band... ");
                testLoadOfflineBand();
                printf("OK\n");
 
+               /* done */
                printf("Testing cell <-> geopoint... ");
                testCellGeoPoint();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_band_get_nearest_pixel... ");
                testNearestPixel();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_band_get_pixel_of_value... ");
                testPixelOfValue();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_pixel_as_polygon... ");
                testPixelAsPolygon();
                printf("OK\n");
 
+               /* done */
                printf("Testing rt_raster_iterator... ");
                testRasterIterator();
                printf("OK\n");
 
+               /* done */
                printf("Test rt_raster_clone... ");
                testRasterClone();
                printf("OK\n");
 
+               /* done */
                printf("Test rt_band_get_pixel_line... ");
                testGetPixelLine();
                printf("OK\n");
diff --git a/raster/test/cunit/Makefile.in b/raster/test/cunit/Makefile.in
new file mode 100644 (file)
index 0000000..e0c3cc1
--- /dev/null
@@ -0,0 +1,107 @@
+# **********************************************************************
+# * $Id: Makefile.in
+# *
+# * PostGIS - Spatial Types for PostgreSQL
+# * http://postgis.refractions.net
+# * Copyright 2008 Paul Ramsey, Mark Cave-Ayland
+# *
+# * This is free software; you can redistribute and/or modify it under
+# * the terms of the GNU General Public Licence. See the COPYING file.
+# *
+# **********************************************************************
+
+CC=@CC@
+top_builddir = @top_builddir@
+SHELL = @SHELL@
+LIBTOOL = @LIBTOOL@
+
+RT_CORE=../../rt_core
+
+LIBLWGEOM_LDFLAGS=../../../liblwgeom/.libs/liblwgeom.a
+LIBLWGEOM_CFLAGS=-I../../../liblwgeom
+LIBGDAL_CFLAGS=@LIBGDAL_CFLAGS@
+LIBGDAL_LDFLAGS=@LIBGDAL_LDFLAGS@
+PROJ_CFLAGS=@PROJ_CPPFLAGS@
+GEOS_CFLAGS=@GEOS_CPPFLAGS@
+GEOS_LDFLAGS=@GEOS_LDFLAGS@ -lgeos_c
+
+RTCORE_CFLAGS=-I$(RT_CORE)
+RTCORE_LDFLAGS=$(RT_CORE)/librtcore.a
+
+CC=@CC@
+CFLAGS = \
+       @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ \
+       $(RTCORE_CFLAGS) \
+       $(LIBLWGEOM_CFLAGS) \
+       $(PROJ_CFLAGS) \
+       $(LIBGDAL_CFLAGS) \
+       $(GEOS_CFLAGS)
+
+LDFLAGS = \
+       $(RTCORE_LDFLAGS) \
+       $(LIBLWGEOM_LDFLAGS) \
+       $(LIBGDAL_LDFLAGS) \
+       $(GEOS_LDFLAGS) \
+       -lm \
+
+CUNIT_LDFLAGS=@CUNIT_LDFLAGS@
+CUNIT_CPPFLAGS=@CUNIT_CPPFLAGS@ -I..
+
+# ADD YOUR NEW TEST FILE HERE (1/1)
+OBJS=  \
+       cu_pixtype.o \
+       cu_raster_basics.o \
+       cu_band_basics.o \
+       cu_raster_wkb.o \
+       cu_raster_geometry.o \
+       cu_raster_misc.o \
+       cu_band_stats.o \
+       cu_band_misc.o \
+       cu_gdal.o \
+       cu_spatial_relationship.o \
+       cu_mapalgebra.o \
+       cu_tester.o 
+
+# If we couldn't find the cunit library then display a helpful message
+ifeq ($(CUNIT_LDFLAGS),)
+all: requirements_not_met_cunit
+check: requirements_not_met_cunit
+else
+
+# Build the unit tester
+all: cu_tester
+
+# Build and run the unit tester
+check: cu_tester
+       @./cu_tester
+
+endif
+
+# Build the main unit test executable
+cu_tester: $(RT_CORE)/librtcore.a $(OBJS)
+       $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(CUNIT_LDFLAGS)
+
+# Command to build each of the .o files
+$(OBJS): %.o: %.c
+       $(CC) $(CFLAGS) $(CUNIT_CPPFLAGS) -c -o $@ $<
+
+$(RT_CORE)/librtcore.a:
+       $(MAKE) -C ../../rt_core
+
+# Clean target
+clean:
+       rm -rf .libs
+       rm -f $(OBJS)
+       rm -f cu_tester
+
+distclean: clean
+       rm -f Makefile
+
+# Requirements message
+requirements_not_met_cunit:
+       @echo
+       @echo "WARNING:"
+       @echo
+       @echo "configure was unable to find CUnit which is required for unit testing."
+       @echo "In order to enable unit testing, you must install CUnit and then re-run configure."
+       @echo
diff --git a/raster/test/cunit/cu_band_basics.c b/raster/test/cunit/cu_band_basics.c
new file mode 100644 (file)
index 0000000..0f46784
--- /dev/null
@@ -0,0 +1,1272 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_band_metadata() {
+       rt_raster rast = NULL;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int temp = 0;
+       double val = 0;
+       char *path = "../regress/loader/testraster.tif";
+       uint8_t extband = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(sizeof(uint8_t) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, sizeof(uint8_t) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               PT_8BUI,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+
+       /* isoffline */
+       CU_ASSERT(!rt_band_is_offline(band));
+
+       /* data */
+       CU_ASSERT(rt_band_get_data(band) != NULL);
+
+       /* ownsdata */
+       CU_ASSERT(!rt_band_get_ownsdata_flag(band));
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       /* dimensions */
+       CU_ASSERT_EQUAL(rt_band_get_width(band), width);
+       CU_ASSERT_EQUAL(rt_band_get_height(band), height);
+
+       /* pixtype */
+       CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_8BUI);
+
+       /* hasnodata */
+       CU_ASSERT(!rt_band_get_hasnodata_flag(band));
+       rt_band_set_hasnodata_flag(band, 1);
+       CU_ASSERT(rt_band_get_hasnodata_flag(band));
+
+       /* nodataval */
+       CU_ASSERT_EQUAL(rt_band_set_nodata(band, 0, &temp), ES_NONE);
+       CU_ASSERT(!temp);
+       CU_ASSERT_EQUAL(rt_band_get_nodata(band, &val), ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       /* clamped nodataval */
+       CU_ASSERT_EQUAL(rt_band_set_nodata(band, -1, &temp), ES_NONE);
+       CU_ASSERT(temp);
+       CU_ASSERT_EQUAL(rt_band_get_nodata(band, &val), ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       /* isnodata */
+       CU_ASSERT(!rt_band_get_isnodata_flag(band));
+       rt_band_check_is_nodata(band);
+       CU_ASSERT(rt_band_get_isnodata_flag(band));
+
+       rt_band_destroy(band);
+       band = NULL;
+       data = NULL;
+       rast = NULL;
+
+       /* offline band */
+       width = 10;
+       height = 10;
+       band = rt_band_new_offline(
+               width, height,
+               PT_8BUI,
+               0, 0,
+               2, path
+       );
+       CU_ASSERT(band != NULL);
+
+       rast = rt_raster_new(width, height);
+       CU_ASSERT(rast != NULL);
+       rt_raster_set_offsets(rast, 80, 80);
+       CU_ASSERT_NOT_EQUAL(rt_raster_add_band(rast, band, 0), -1);
+
+       /* isoffline */
+       CU_ASSERT(rt_band_is_offline(band));
+
+       /* ext path */
+       CU_ASSERT_STRING_EQUAL(rt_band_get_ext_path(band), path);
+
+       /* ext band number */
+       CU_ASSERT_EQUAL(rt_band_get_ext_band_num(band, &extband), ES_NONE);
+       CU_ASSERT_EQUAL(extband, 2);
+
+       /* band data */
+       CU_ASSERT_EQUAL(rt_band_load_offline_data(band), ES_NONE);
+       CU_ASSERT(rt_band_get_data(band) != NULL);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       CU_ASSERT_EQUAL(rt_band_get_pixel(band, x, y, &val, NULL), ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 255, 1.);
+               }
+       }
+
+       /* test rt_band_check_is_nodata */
+       rtdealloc(band->data.offline.mem);
+       band->data.offline.mem = NULL;
+       CU_ASSERT_EQUAL(rt_band_check_is_nodata(band), FALSE);
+
+       cu_free_raster(rast);
+}
+
+static void test_band_pixtype_1BB() {
+       rt_pixtype pixtype = PT_1BB;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 2, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_nodata(band, 3, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_pixel(band, 0, 0, 2, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_pixel(band, 0, 0, 3, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       for (x = 0; x < rt_band_get_width(band); ++x) {
+               for ( y = 0; y < rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_2BUI() {
+       rt_pixtype pixtype = PT_2BUI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 2, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 3, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 3, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 4, &clamped); /* invalid: out of range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_nodata(band, 5, &clamped); /* invalid: out of range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_pixel(band, 0, 0, 4, &clamped); /* out of range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_pixel(band, 0, 0, 5, &clamped); /* out of range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 2, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 3, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 3, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_4BUI() {
+       rt_pixtype pixtype = PT_4BUI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 2, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 4, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 4, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 8, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 8, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 15, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 15, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 16, &clamped);  /* out of value range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_nodata(band, 17, &clamped);  /* out of value range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_pixel(band, 0, 0, 35, &clamped); /* out of value range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 3, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 3, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 7, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 7, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 15, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 15, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_8BUI() {
+       rt_pixtype pixtype = PT_8BUI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 2, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 4, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 4, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 8, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 8, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 15, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 15, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 31, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 31, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 255, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 256, &clamped); /* out of value range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       err = rt_band_set_pixel(band, 0, 0, 256, &clamped); /* out of value range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 31, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 31, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 255, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_8BSI() {
+       rt_pixtype pixtype = PT_8BSI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 2, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 4, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 4, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 8, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 8, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 15, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 15, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 31, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 31, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, -127, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, -127, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 127, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 127, DBL_EPSILON);
+
+       /* out of range (-127..127) */
+       err = rt_band_set_nodata(band, -129, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of range (-127..127) */
+       err = rt_band_set_nodata(band, 129, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of range (-127..127) */
+       err = rt_band_set_pixel(band, 0, 0, -129, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of range (-127..127) */
+       err = rt_band_set_pixel(band, 0, 0, 129, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 31, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 31, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, -127, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, -127, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 127, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 127, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_16BUI() {
+       rt_pixtype pixtype = PT_16BUI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 31, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 31, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 255, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 65535, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 65535, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 65536, &clamped); /* out of range */
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of value range */
+       err = rt_band_set_pixel(band, 0, 0, 65536, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of dimensions range */
+       err = rt_band_set_pixel(band, rt_band_get_width(band), 0, 0, &clamped);
+       CU_ASSERT((err != ES_NONE));
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 255, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 65535, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 65535, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_16BSI() {
+       rt_pixtype pixtype = PT_16BSI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 31, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 31, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 255, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, -32767, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, -32767, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 32767, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 32767, DBL_EPSILON);
+
+       /* out of range (-32767..32767) */
+       err = rt_band_set_nodata(band, -32769, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of range (-32767..32767) */
+       err = rt_band_set_nodata(band, 32769, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of range (-32767..32767) */
+       err = rt_band_set_pixel(band, 0, 0, -32769, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of range (-32767..32767) */
+       err = rt_band_set_pixel(band, 0, 0, 32769, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of dimensions range */
+       err = rt_band_set_pixel(band, rt_band_get_width(band), 0, 0, NULL);
+       CU_ASSERT((err != ES_NONE));
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 255, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, -32767, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, -32767, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 32767, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 32767, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_32BUI() {
+       rt_pixtype pixtype = PT_32BUI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 65535, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 65535, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 4294967295UL, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 4294967295UL, DBL_EPSILON);
+
+       /* out of range */
+       err = rt_band_set_nodata(band, 4294967296ULL, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of value range */
+       err = rt_band_set_pixel(band, 0, 0, 4294967296ULL, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of dimensions range */
+       err = rt_band_set_pixel(band, rt_band_get_width(band), 0, 4294967296ULL, NULL);
+       CU_ASSERT((err != ES_NONE));
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 65535, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 65535, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 4294967295UL, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 4294967295UL, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_32BSI() {
+       rt_pixtype pixtype = PT_32BSI;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 65535, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 65535, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 2147483647, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       /*printf("32BSI pix is %ld\n", (long int)val);*/
+       CU_ASSERT_DOUBLE_EQUAL(val, 2147483647, DBL_EPSILON);
+
+       /* out of range */
+       err = rt_band_set_nodata(band, 2147483648UL, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of value range */
+       err = rt_band_set_pixel(band, 0, 0, 2147483648UL, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(clamped);
+
+       /* out of dimensions range */
+       err = rt_band_set_pixel(band, rt_band_get_width(band), 0, 0, NULL);
+       CU_ASSERT((err != ES_NONE));
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 65535, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 65535, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 2147483647, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 2147483647, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_32BF() {
+       rt_pixtype pixtype = PT_32BF;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 65535.5, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 65535.5, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0.006, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0.0060000000521540, DBL_EPSILON);
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 65535.5, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 65535.5, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0.006, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0.0060000000521540, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_pixtype_64BF() {
+       rt_pixtype pixtype = PT_64BF;
+       uint8_t *data = NULL;
+       rt_band band = NULL;
+       int width = 5;
+       int height = 5;
+       int err = 0;
+       int clamped = 0;
+       double val = 0;
+       int x;
+       int y;
+
+       /* inline band */
+       data = rtalloc(rt_pixtype_size(pixtype) * width * height);
+       CU_ASSERT(data != NULL);
+       memset(data, 0, rt_pixtype_size(pixtype) * width * height);
+
+       band = rt_band_new_inline(
+               width, height,
+               pixtype,
+               0, 0,
+               data
+       );
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+       CU_ASSERT(rt_band_get_ownsdata_flag(band));
+
+       err = rt_band_set_nodata(band, 1, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 65535.56, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 65535.56, DBL_EPSILON);
+
+       err = rt_band_set_nodata(band, 0.006, &clamped);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(!clamped);
+       rt_band_get_nodata(band, &val);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0.006, DBL_EPSILON);
+
+       for (x=0; x<rt_band_get_width(band); ++x) {
+               for (y=0; y<rt_band_get_height(band); ++y) {
+                       err = rt_band_set_pixel(band, x, y, 1, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 65535.56, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 65535.56, DBL_EPSILON);
+
+                       err = rt_band_set_pixel(band, x, y, 0.006, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       err = rt_band_get_pixel(band, x, y, &val, NULL);
+                       CU_ASSERT_EQUAL(err, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(val, 0.006, DBL_EPSILON);
+               }
+       }
+
+       rt_band_destroy(band);
+}
+
+static void test_band_get_pixel_line() {
+       rt_raster rast;
+       rt_band band;
+       int maxX = 5;
+       int maxY = 5;
+       int x = 0;
+       int y = 0;
+       void *vals = NULL;
+       uint16_t nvals = 0;
+       int err = 0;
+
+       rast = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast != NULL);
+
+       rt_raster_set_scale(rast, 1, -1);
+
+       band = cu_add_band(rast, PT_8BSI, 0, 0);
+       CU_ASSERT(band != NULL);
+
+       for (y = 0; y < maxY; y++) {
+               for (x = 0; x < maxX; x++)
+                       rt_band_set_pixel(band, x, y, x + (y * maxX), NULL);
+       }
+
+       err = rt_band_get_pixel_line(band, 0, 0, maxX, &vals, &nvals);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT_EQUAL(nvals, maxX);
+       CU_ASSERT_EQUAL(((int8_t *) vals)[3], 3);
+       rtdealloc(vals);
+       
+       err = rt_band_get_pixel_line(band, 4, 4, maxX, &vals, &nvals);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT_EQUAL(nvals, 1);
+       CU_ASSERT_EQUAL(((int8_t *) vals)[0], 24);
+       rtdealloc(vals);
+
+       err = rt_band_get_pixel_line(band, maxX, maxY, maxX, &vals, &nvals);
+       CU_ASSERT_NOT_EQUAL(err, ES_NONE);
+
+       cu_free_raster(rast);
+}
+
+/* register tests */
+CU_TestInfo band_basics_tests[] = {
+       PG_TEST(test_band_metadata),
+       PG_TEST(test_band_pixtype_1BB),
+       PG_TEST(test_band_pixtype_2BUI),
+       PG_TEST(test_band_pixtype_4BUI),
+       PG_TEST(test_band_pixtype_8BUI),
+       PG_TEST(test_band_pixtype_8BSI),
+       PG_TEST(test_band_pixtype_16BUI),
+       PG_TEST(test_band_pixtype_16BSI),
+       PG_TEST(test_band_pixtype_32BUI),
+       PG_TEST(test_band_pixtype_32BSI),
+       PG_TEST(test_band_pixtype_32BF),
+       PG_TEST(test_band_pixtype_64BF),
+       PG_TEST(test_band_get_pixel_line),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo band_basics_suite = {"band_basics",  NULL,  NULL, band_basics_tests};
diff --git a/raster/test/cunit/cu_band_misc.c b/raster/test/cunit/cu_band_misc.c
new file mode 100644 (file)
index 0000000..d10e3dd
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_band_get_nearest_pixel() {
+       rt_raster rast;
+       rt_band band;
+       uint32_t x, y;
+       int rtn;
+       const int maxX = 10;
+       const int maxY = 10;
+       rt_pixel npixels = NULL;
+
+       double **value;
+       int **nodata;
+       int dimx;
+       int dimy;
+
+       rast = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast != NULL);
+
+       band = cu_add_band(rast, PT_32BUI, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       for (x = 0; x < maxX; x++) {
+               for (y = 0; y < maxY; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, 1, NULL);
+               }
+       }
+
+       rt_band_set_pixel(band, 0, 0, 0, NULL);
+       rt_band_set_pixel(band, 3, 0, 0, NULL);
+       rt_band_set_pixel(band, 6, 0, 0, NULL);
+       rt_band_set_pixel(band, 9, 0, 0, NULL);
+       rt_band_set_pixel(band, 1, 2, 0, NULL);
+       rt_band_set_pixel(band, 4, 2, 0, NULL);
+       rt_band_set_pixel(band, 7, 2, 0, NULL);
+       rt_band_set_pixel(band, 2, 4, 0, NULL);
+       rt_band_set_pixel(band, 5, 4, 0, NULL);
+       rt_band_set_pixel(band, 8, 4, 0, NULL);
+       rt_band_set_pixel(band, 0, 6, 0, NULL);
+       rt_band_set_pixel(band, 3, 6, 0, NULL);
+       rt_band_set_pixel(band, 6, 6, 0, NULL);
+       rt_band_set_pixel(band, 9, 6, 0, NULL);
+       rt_band_set_pixel(band, 1, 8, 0, NULL);
+       rt_band_set_pixel(band, 4, 8, 0, NULL);
+       rt_band_set_pixel(band, 7, 8, 0, NULL);
+
+       /* 0,0 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               0, 0,
+               0, 0,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 3);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 1,1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               1, 1,
+               0, 0,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 6);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 4,4 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               4, 4,
+               0, 0,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 7);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 4,4 distance 2 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               4, 4,
+               2, 2,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 19);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 10,10 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               10, 10,
+               0, 0,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 1);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 11,11 distance 1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               11, 11,
+               1, 1,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 0);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* -1,-1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               -1, -1,
+               0, 0,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 3);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* -1,-1 distance 1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               -1, -1,
+               1, 1,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 0);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* -1,1 distance 1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               -1, 1,
+               1, 1,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 2);
+
+       rtn = rt_pixel_set_to_array(
+               npixels, rtn,
+               -1, 1, 
+               1, 1,
+               &value,
+               &nodata,
+               &dimx, &dimy
+       );
+       rtdealloc(npixels);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(dimx, 3);
+       CU_ASSERT_EQUAL(dimy, 3);
+
+       for (x = 0; x < dimx; x++) {
+               rtdealloc(nodata[x]);
+               rtdealloc(value[x]);
+       }
+
+       rtdealloc(nodata);
+       rtdealloc(value);
+
+
+       /* -2,2 distance 1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               -2, 2,
+               1, 1,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 0);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* -10,2 distance 3 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               -10, 2,
+               3, 3,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 0);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* -10,2 distance 3 include NODATA */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               -10, 2,
+               3, 3,
+               0,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 48);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 4,4 distance 3,2 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               4, 4,
+               3, 2,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 27);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 2,7 distance 3,1 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               2, 7,
+               3, 1,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 13);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* 10,10 distance 1,3 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               10,10,
+               1, 3,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 3);
+       if (rtn)
+               rtdealloc(npixels);
+
+       /* band with no NODATA */
+       band = cu_add_band(rast, PT_32BUI, 0, 0);
+       CU_ASSERT(band != NULL);
+
+       /* 0,0 */
+       rtn = rt_band_get_nearest_pixel(
+               band,
+               0, 0,
+               0, 0,
+               1,
+               &npixels
+       );
+       CU_ASSERT_EQUAL(rtn, 8);
+       if (rtn)
+               rtdealloc(npixels);
+
+       cu_free_raster(rast);
+}
+
+static void test_band_get_pixel_of_value() {
+       rt_raster rast;
+       rt_band band;
+       uint32_t x, y;
+       int rtn;
+       const int maxX = 10;
+       const int maxY = 10;
+       rt_pixel pixels = NULL;
+
+       double search0[1] = {0};
+       double search1[1] = {1};
+       double search2[2] = {3, 5};
+
+       rast = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast != NULL);
+
+       band = cu_add_band(rast, PT_32BUI, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       for (x = 0; x < maxX; x++) {
+               for (y = 0; y < maxY; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, 1, NULL);
+               }
+       }
+
+       rt_band_set_pixel(band, 0, 0, 0, NULL);
+       rt_band_set_pixel(band, 3, 0, 0, NULL);
+       rt_band_set_pixel(band, 6, 0, 0, NULL);
+       rt_band_set_pixel(band, 9, 0, 0, NULL);
+       rt_band_set_pixel(band, 1, 2, 0, NULL);
+       rt_band_set_pixel(band, 4, 2, 0, NULL);
+       rt_band_set_pixel(band, 7, 2, 0, NULL);
+       rt_band_set_pixel(band, 2, 4, 0, NULL);
+       rt_band_set_pixel(band, 5, 4, 0, NULL);
+       rt_band_set_pixel(band, 8, 4, 0, NULL);
+       rt_band_set_pixel(band, 0, 6, 0, NULL);
+       rt_band_set_pixel(band, 3, 6, 0, NULL);
+       rt_band_set_pixel(band, 6, 6, 0, NULL);
+       rt_band_set_pixel(band, 9, 6, 0, NULL);
+       rt_band_set_pixel(band, 1, 8, 0, NULL);
+       rt_band_set_pixel(band, 4, 8, 0, NULL);
+       rt_band_set_pixel(band, 7, 8, 0, NULL);
+
+       pixels = NULL;
+       rtn = rt_band_get_pixel_of_value(
+               band, TRUE,
+               search1, 1,
+               &pixels
+       );
+       CU_ASSERT_EQUAL(rtn, 83);
+       if (rtn)
+               rtdealloc(pixels);
+
+       pixels = NULL;
+       rtn = rt_band_get_pixel_of_value(
+               band, FALSE,
+               search0, 1,
+               &pixels
+       );
+       CU_ASSERT_EQUAL(rtn, 17);
+       if (rtn)
+               rtdealloc(pixels);
+
+       rt_band_set_pixel(band, 4, 2, 3, NULL);
+       rt_band_set_pixel(band, 7, 2, 5, NULL);
+       rt_band_set_pixel(band, 1, 8, 3, NULL);
+
+       pixels = NULL;
+       rtn = rt_band_get_pixel_of_value(
+               band, TRUE,
+               search2, 2,
+               &pixels
+       );
+       CU_ASSERT_EQUAL(rtn, 3);
+       if (rtn)
+               rtdealloc(pixels);
+
+       cu_free_raster(rast);
+}
+
+/* register tests */
+CU_TestInfo band_misc_tests[] = {
+       PG_TEST(test_band_get_nearest_pixel),
+       PG_TEST(test_band_get_pixel_of_value),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo band_misc_suite = {"band_misc",  NULL,  NULL, band_misc_tests};
diff --git a/raster/test/cunit/cu_band_stats.c b/raster/test/cunit/cu_band_stats.c
new file mode 100644 (file)
index 0000000..3dd1748
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_band_stats() {
+       rt_bandstats stats = NULL;
+       rt_histogram histogram = NULL;
+       double bin_width[] = {100};
+       double quantiles[] = {0.1, 0.3, 0.5, 0.7, 0.9};
+       double quantiles2[] = {0.66666667};
+       rt_quantile quantile = NULL;
+       uint32_t count = 0;
+
+       rt_raster raster;
+       rt_band band;
+       uint32_t x;
+       uint32_t xmax = 100;
+       uint32_t y;
+       uint32_t ymax = 100;
+       uint32_t max_run;
+       double nodata;
+       int rtn;
+
+       uint32_t values[] = {0, 91, 55, 86, 76, 41, 36, 97, 25, 63, 68, 2, 78, 15, 82, 47};
+       struct quantile_llist *qlls = NULL;
+       uint32_t qlls_count;
+
+       raster = rt_raster_new(xmax, ymax);
+       CU_ASSERT(raster != NULL);
+       band = cu_add_band(raster, PT_32BUI, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       for (x = 0; x < xmax; x++) {
+               for (y = 0; y < ymax; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, x + y, NULL);
+               }
+       }
+
+       rt_band_get_nodata(band, &nodata);
+       CU_ASSERT_DOUBLE_EQUAL(nodata, 0, DBL_EPSILON);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 1, 0, 1, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+       CU_ASSERT_DOUBLE_EQUAL(stats->min, 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(stats->max, 198, DBL_EPSILON);
+
+       quantile = (rt_quantile) rt_band_get_quantiles(stats, NULL, 0, &count);
+       CU_ASSERT(quantile != NULL);
+       rtdealloc(quantile);
+
+       histogram = (rt_histogram) rt_band_get_histogram(stats, 0, NULL, 0, 0, 0, 0, &count);
+       CU_ASSERT(histogram != NULL);
+       rtdealloc(histogram);
+
+       histogram = (rt_histogram) rt_band_get_histogram(stats, 0, NULL, 0, 1, 0, 0, &count);
+       CU_ASSERT(histogram != NULL);
+       rtdealloc(histogram);
+
+       histogram = (rt_histogram) rt_band_get_histogram(stats, 0, bin_width, 1, 0, 0, 0, &count);
+       CU_ASSERT(histogram != NULL);
+       rtdealloc(histogram);
+
+       rtdealloc(stats->values);
+       rtdealloc(stats);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 1, 0.1, 1, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+
+       quantile = (rt_quantile) rt_band_get_quantiles(stats, NULL, 0, &count);
+       CU_ASSERT(quantile != NULL);
+       rtdealloc(quantile);
+
+       quantile = (rt_quantile) rt_band_get_quantiles(stats, quantiles, 5, &count);
+       CU_ASSERT(quantile != NULL);
+       CU_ASSERT_EQUAL(count, 5);
+       rtdealloc(quantile);
+
+       histogram = (rt_histogram) rt_band_get_histogram(stats, 0, NULL, 0, 0, 0, 0, &count);
+       CU_ASSERT(histogram != NULL);
+       rtdealloc(histogram);
+
+       rtdealloc(stats->values);
+       rtdealloc(stats);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 1, 0.15, 0, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+       rtdealloc(stats);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 1, 0.2, 0, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+       rtdealloc(stats);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 1, 0.25, 0, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+       rtdealloc(stats);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 0, 0, 1, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+       CU_ASSERT_DOUBLE_EQUAL(stats->min, 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(stats->max, 198, DBL_EPSILON);
+
+       quantile = (rt_quantile) rt_band_get_quantiles(stats, NULL, 0, &count);
+       CU_ASSERT(quantile != NULL);
+       rtdealloc(quantile);
+
+       rtdealloc(stats->values);
+       rtdealloc(stats);
+
+       stats = (rt_bandstats) rt_band_get_summary_stats(band, 0, 0.1, 1, NULL, NULL, NULL);
+       CU_ASSERT(stats != NULL);
+
+       quantile = (rt_quantile) rt_band_get_quantiles(stats, NULL, 0, &count);
+       CU_ASSERT(quantile != NULL);
+       rtdealloc(quantile);
+
+       rtdealloc(stats->values);
+       rtdealloc(stats);
+
+       cu_free_raster(raster);
+
+       xmax = 4;
+       ymax = 4;
+       raster = rt_raster_new(4, 4);
+       CU_ASSERT(raster != NULL);
+       band = cu_add_band(raster, PT_8BUI, 0, 0);
+       CU_ASSERT(band != NULL);
+       rt_band_set_nodata(band, 0, NULL);
+
+       for (x = 0; x < xmax; x++) {
+               for (y = 0; y < ymax; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, values[(x * ymax) + y], NULL);
+               }
+       }
+
+       rt_band_get_nodata(band, &nodata);
+       CU_ASSERT_DOUBLE_EQUAL(nodata, 0, DBL_EPSILON);
+
+       quantile = (rt_quantile) rt_band_get_quantiles_stream(
+               band, 1, 1, 15,
+               &qlls, &qlls_count,
+               quantiles2, 1,
+               &count);
+       CU_ASSERT(quantile != NULL);
+       CU_ASSERT_NOT_EQUAL(count, 0);
+       CU_ASSERT_NOT_EQUAL(qlls_count, 0);
+       CU_ASSERT_DOUBLE_EQUAL(quantile[0].value, 78, DBL_EPSILON);
+       rtdealloc(quantile);
+       quantile_llist_destroy(&qlls, qlls_count);
+       qlls = NULL;
+       qlls_count = 0;
+
+       cu_free_raster(raster);
+
+       xmax = 100;
+       ymax = 100;
+       raster = rt_raster_new(xmax, ymax);
+       CU_ASSERT(raster != NULL);
+       band = cu_add_band(raster, PT_64BF, 0, 0);
+       CU_ASSERT(band != NULL);
+       rt_band_set_nodata(band, 0, NULL);
+
+       for (x = 0; x < xmax; x++) {
+               for (y = 0; y < ymax; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, (((double) x * y) + (x + y) + (x + y * x)) / (x + y + 1), NULL);
+               }
+       }
+
+       rt_band_get_nodata(band, &nodata);
+       CU_ASSERT_DOUBLE_EQUAL(nodata, 0, DBL_EPSILON);
+
+       max_run = 5;
+       for (x = 0; x < max_run; x++) {
+               quantile = (rt_quantile) rt_band_get_quantiles_stream(
+                       band, 1, 1, xmax * ymax * max_run,
+                       &qlls, &qlls_count,
+                       quantiles2, 1,
+                       &count);
+               CU_ASSERT(quantile != NULL);
+               CU_ASSERT_NOT_EQUAL(count, 0);
+               CU_ASSERT_NOT_EQUAL(qlls_count, 0);
+               rtdealloc(quantile);
+       }
+
+       quantile_llist_destroy(&qlls, qlls_count);
+       qlls = NULL;
+       qlls_count = 0;
+
+       cu_free_raster(raster);
+}
+
+static void test_band_value_count() {
+       rt_valuecount vcnts = NULL;
+
+       rt_raster raster;
+       rt_band band;
+       uint32_t x;
+       uint32_t xmax = 100;
+       uint32_t y;
+       uint32_t ymax = 100;
+       uint32_t rtn = 0;
+
+       double count[] = {3, 4, 5};
+
+       raster = rt_raster_new(xmax, ymax);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+       band = cu_add_band(raster, PT_64BF, 0, 0);
+       CU_ASSERT(band != NULL);
+       rt_band_set_nodata(band, 0, NULL);
+
+       for (x = 0; x < xmax; x++) {
+               for (y = 0; y < ymax; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, (((double) x * y) + (x + y) + (x + y * x)) / (x + y + 1), NULL);
+               }
+       }
+       vcnts = rt_band_get_value_count(band, 1, NULL, 0, 0, NULL, &rtn);
+       CU_ASSERT(vcnts != NULL);
+       CU_ASSERT_NOT_EQUAL(rtn, 0);
+       rtdealloc(vcnts);
+
+       vcnts = rt_band_get_value_count(band, 1, NULL, 0, 0.01, NULL, &rtn);
+       CU_ASSERT(vcnts != NULL);
+       CU_ASSERT_NOT_EQUAL(rtn, 0);
+       rtdealloc(vcnts);
+
+       vcnts = rt_band_get_value_count(band, 1, NULL, 0, 0.1, NULL, &rtn);
+       CU_ASSERT(vcnts != NULL);
+       CU_ASSERT_NOT_EQUAL(rtn, 0);
+       rtdealloc(vcnts);
+
+       vcnts = rt_band_get_value_count(band, 1, NULL, 0, 1, NULL, &rtn);
+       CU_ASSERT(vcnts != NULL);
+       CU_ASSERT_NOT_EQUAL(rtn, 0);
+       rtdealloc(vcnts);
+
+       vcnts = rt_band_get_value_count(band, 1, NULL, 0, 10, NULL, &rtn);
+       CU_ASSERT(vcnts != NULL);
+       CU_ASSERT_NOT_EQUAL(rtn, 0);
+       rtdealloc(vcnts);
+
+       vcnts = rt_band_get_value_count(band, 1, count, 3, 1, NULL, &rtn);
+       CU_ASSERT(vcnts != NULL);
+       CU_ASSERT_NOT_EQUAL(rtn, 0);
+       rtdealloc(vcnts);
+
+       cu_free_raster(raster);
+}
+
+/* register tests */
+CU_TestInfo band_stats_tests[] = {
+       PG_TEST(test_band_stats),
+       PG_TEST(test_band_value_count),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo band_stats_suite = {"band_stats",  NULL,  NULL, band_stats_tests};
diff --git a/raster/test/cunit/cu_gdal.c b/raster/test/cunit/cu_gdal.c
new file mode 100644 (file)
index 0000000..699a004
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_gdal_configured() {
+       CU_ASSERT(rt_util_gdal_configured());
+}
+
+static void test_gdal_drivers() {
+       int i;
+       uint32_t size;
+       rt_gdaldriver drv = NULL;
+
+       drv = (rt_gdaldriver) rt_raster_gdal_drivers(&size, 1);
+       CU_ASSERT(drv != NULL);
+
+       for (i = 0; i < size; i++) {
+               CU_ASSERT(strlen(drv[i].short_name));
+               rtdealloc(drv[i].short_name);
+               rtdealloc(drv[i].long_name);
+               rtdealloc(drv[i].create_options);
+       }
+
+       rtdealloc(drv);
+}
+
+static void test_gdal_rasterize() {
+       rt_raster raster;
+       char srs[] = "PROJCS[\"unnamed\",GEOGCS[\"unnamed ellipse\",DATUM[\"unknown\",SPHEROID[\"unnamed\",6370997,0]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],PARAMETER[\"latitude_of_center\",45],PARAMETER[\"longitude_of_center\",-100],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1],AUTHORITY[\"EPSG\",\"2163\"]]";
+       const char wkb_hex[] = "010300000001000000050000000000000080841ec100000000600122410000000080841ec100000000804f22410000000040e81dc100000000804f22410000000040e81dc100000000600122410000000080841ec10000000060012241";
+       const char *pos = wkb_hex;
+       unsigned char *wkb = NULL;
+       int wkb_len = 0;
+       int i;
+       double scale_x = 100;
+       double scale_y = -100;
+
+       rt_pixtype pixtype[] = {PT_8BUI};
+       double init[] = {0};
+       double value[] = {1};
+       double nodata[] = {0};
+       uint8_t nodata_mask[] = {1};
+
+       /* hex to byte */
+       wkb_len = (int) ceil(((double) strlen(wkb_hex)) / 2);
+       wkb = (unsigned char *) rtalloc(sizeof(unsigned char) * wkb_len);
+       for (i = 0; i < wkb_len; i++) {
+               sscanf(pos, "%2hhx", &wkb[i]);
+               pos += 2;
+       }
+
+       raster = rt_raster_gdal_rasterize(
+               wkb,
+               wkb_len, srs,
+               1, pixtype,
+               init, value,
+               nodata, nodata_mask,
+               NULL, NULL,
+               &scale_x, &scale_y,
+               NULL, NULL,
+               NULL, NULL,
+               NULL, NULL,
+               NULL
+       );
+
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 100);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 100);
+       CU_ASSERT_NOT_EQUAL(rt_raster_get_num_bands(raster), 0);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), -500000, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 600000, DBL_EPSILON);
+
+       rtdealloc(wkb);
+       cu_free_raster(raster);
+}
+
+static char *
+lwgeom_to_text(const LWGEOM *lwgeom) {
+       char *wkt;
+       size_t wkt_size;
+
+       wkt = lwgeom_to_wkt(lwgeom, WKT_ISO, DBL_DIG, &wkt_size);
+
+       return wkt;
+}
+
+static rt_raster fillRasterToPolygonize(int hasnodata, double nodataval) {
+       rt_band band = NULL;
+       rt_pixtype pixtype = PT_32BF;
+
+       /* Create raster */
+       uint16_t width = 9;
+       uint16_t height = 9;
+
+       rt_raster raster = rt_raster_new(width, height);
+       rt_raster_set_scale(raster, 1, 1);
+
+       band = cu_add_band(raster, pixtype, hasnodata, nodataval);
+       CU_ASSERT(band != NULL);
+
+       {
+               int x, y;
+               for (x = 0; x < rt_band_get_width(band); ++x)
+                       for (y = 0; y < rt_band_get_height(band); ++y)
+                               rt_band_set_pixel(band, x, y, 0.0, NULL);
+       } 
+
+       rt_band_set_pixel(band, 3, 1, 1.8, NULL);
+       rt_band_set_pixel(band, 4, 1, 1.8, NULL);
+       rt_band_set_pixel(band, 5, 1, 2.8, NULL);
+       rt_band_set_pixel(band, 2, 2, 1.8, NULL);
+       rt_band_set_pixel(band, 3, 2, 1.8, NULL);
+       rt_band_set_pixel(band, 4, 2, 1.8, NULL);
+       rt_band_set_pixel(band, 5, 2, 2.8, NULL);
+       rt_band_set_pixel(band, 6, 2, 2.8, NULL);
+       rt_band_set_pixel(band, 1, 3, 1.8, NULL);
+       rt_band_set_pixel(band, 2, 3, 1.8, NULL);
+       rt_band_set_pixel(band, 6, 3, 2.8, NULL);
+       rt_band_set_pixel(band, 7, 3, 2.8, NULL);
+       rt_band_set_pixel(band, 1, 4, 1.8, NULL);
+       rt_band_set_pixel(band, 2, 4, 1.8, NULL);
+       rt_band_set_pixel(band, 6, 4, 2.8, NULL);
+       rt_band_set_pixel(band, 7, 4, 2.8, NULL);
+       rt_band_set_pixel(band, 1, 5, 1.8, NULL);
+       rt_band_set_pixel(band, 2, 5, 1.8, NULL);
+       rt_band_set_pixel(band, 6, 5, 2.8, NULL);
+       rt_band_set_pixel(band, 7, 5, 2.8, NULL);
+       rt_band_set_pixel(band, 2, 6, 1.8, NULL);
+       rt_band_set_pixel(band, 3, 6, 1.8, NULL);
+       rt_band_set_pixel(band, 4, 6, 1.8, NULL);
+       rt_band_set_pixel(band, 5, 6, 2.8, NULL);
+       rt_band_set_pixel(band, 6, 6, 2.8, NULL);
+       rt_band_set_pixel(band, 3, 7, 1.8, NULL);
+       rt_band_set_pixel(band, 4, 7, 1.8, NULL);
+       rt_band_set_pixel(band, 5, 7, 2.8, NULL);
+
+       return raster;
+}
+
+static void test_gdal_polygonize() {
+       int i;
+       rt_raster rt;
+       int nPols = 0;
+       rt_geomval gv = NULL;
+       char *wkt = NULL;
+
+       rt = fillRasterToPolygonize(1, -1.0);
+       CU_ASSERT(rt_raster_has_band(rt, 0));
+
+       nPols = 0;
+       gv = rt_raster_gdal_polygonize(rt, 0, TRUE, &nPols);
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 1.8, FLT_EPSILON);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 2.0, 1.);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[0].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 1,3 2,2 2,2 3,1 3,1 6,2 6,2 7,3 7,3 8,5 8,5 6,3 6,3 3,4 3,5 3,5 1,3 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[1].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 3,3 6,6 6,6 3,3 3))");
+       rtdealloc(wkt);
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 2.8, FLT_EPSILON);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 3.0, 1.);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[2].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[3].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[3].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((0 0,0 9,9 9,9 0,0 0),(6 7,6 8,3 8,3 7,2 7,2 6,1 6,1 3,2 3,2 2,3 2,3 1,6 1,6 2,7 2,7 3,8 3,8 6,7 6,7 7,6 7))");
+       rtdealloc(wkt);
+
+       for (i = 0; i < nPols; i++) lwgeom_free((LWGEOM *) gv[i].geom);
+       rtdealloc(gv);
+       cu_free_raster(rt);
+
+       /* Second test: NODATA value = 1.8 */
+#ifdef GDALFPOLYGONIZE
+       rt = fillRasterToPolygonize(1, 1.8);
+#else
+       rt = fillRasterToPolygonize(1, 2.0);
+#endif
+
+       /* We can check rt_raster_has_band here too */
+       CU_ASSERT(rt_raster_has_band(rt, 0));
+
+       nPols = 0;
+       gv = rt_raster_gdal_polygonize(rt, 0, TRUE, &nPols);
+
+       /*
+       for (i = 0; i < nPols; i++) {
+               wkt = lwgeom_to_text((const LWGEOM *) gv[i].geom);
+               printf("(i, val, geom) = (%d, %f, %s)\n", i, gv[i].val, wkt);
+               rtdealloc(wkt);
+       }
+       */
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[1].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 3,3 6,6 6,6 3,3 3))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 2.8, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[2].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[3].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[3].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((0 0,0 9,9 9,9 0,0 0),(6 7,6 8,3 8,3 7,2 7,2 6,1 6,1 3,2 3,2 2,3 2,3 1,6 1,6 2,7 2,7 3,8 3,8 6,7 6,7 7,6 7))");
+       rtdealloc(wkt);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 0.0, 1.);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[0].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 3,3 6,6 6,6 3,3 3))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 3.0, 1.);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[1].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 0.0, 1.);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[2].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((0 0,0 9,9 9,9 0,0 0),(6 7,6 8,3 8,3 7,2 7,2 6,1 6,1 3,2 3,2 2,3 2,3 1,6 1,6 2,7 2,7 3,8 3,8 6,7 6,7 7,6 7))");
+       rtdealloc(wkt);
+#endif
+
+       for (i = 0; i < nPols; i++) lwgeom_free((LWGEOM *) gv[i].geom);
+       rtdealloc(gv);
+       cu_free_raster(rt);
+
+       /* Third test: NODATA value = 2.8 */
+#ifdef GDALFPOLYGONIZE
+       rt = fillRasterToPolygonize(1, 2.8);
+#else  
+       rt = fillRasterToPolygonize(1, 3.0);
+#endif
+
+       /* We can check rt_raster_has_band here too */
+       CU_ASSERT(rt_raster_has_band(rt, 0));
+
+       nPols = 0;
+       gv = rt_raster_gdal_polygonize(rt, 0, TRUE, &nPols);
+
+       /*
+       for (i = 0; i < nPols; i++) {
+               wkt = lwgeom_to_text((const LWGEOM *) gv[i].geom);
+               printf("(i, val, geom) = (%d, %f, %s)\n", i, gv[i].val, wkt);
+               rtdealloc(wkt);
+       }
+       */
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 1.8, FLT_EPSILON);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[3].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[3].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((0 0,0 9,9 9,9 0,0 0),(6 7,6 8,3 8,3 7,2 7,2 6,1 6,1 3,2 3,2 2,3 2,3 1,6 1,6 2,7 2,7 3,8 3,8 6,7 6,7 7,6 7))");
+       rtdealloc(wkt);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 2.0, 1.);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 0.0, 1.);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[2].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((0 0,0 9,9 9,9 0,0 0),(6 7,6 8,3 8,3 7,2 7,2 6,1 6,1 3,2 3,2 2,3 2,3 1,6 1,6 2,7 2,7 3,8 3,8 6,7 6,7 7,6 7))");
+       rtdealloc(wkt);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[0].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 1,3 2,2 2,2 3,1 3,1 6,2 6,2 7,3 7,3 8,5 8,5 6,3 6,3 3,4 3,5 3,5 1,3 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[1].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 3,3 6,6 6,6 3,3 3))");
+       rtdealloc(wkt);
+
+       for (i = 0; i < nPols; i++) lwgeom_free((LWGEOM *) gv[i].geom);
+       rtdealloc(gv);
+       cu_free_raster(rt);
+
+       /* Fourth test: NODATA value = 0 */
+       rt = fillRasterToPolygonize(1, 0.0);
+       /* We can check rt_raster_has_band here too */
+       CU_ASSERT(rt_raster_has_band(rt, 0));
+
+       nPols = 0;
+       gv = rt_raster_gdal_polygonize(rt, 0, TRUE, &nPols);
+       
+       /*
+       for (i = 0; i < nPols; i++) {
+               wkt = lwgeom_to_text((const LWGEOM *) gv[i].geom);
+               printf("(i, val, geom) = (%d, %f, %s)\n", i, gv[i].val, wkt);
+               rtdealloc(wkt);
+       }
+       */
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 1.8, FLT_EPSILON);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 2.0, 1.);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[0].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 1,3 2,2 2,2 3,1 3,1 6,2 6,2 7,3 7,3 8,5 8,5 6,3 6,3 3,4 3,5 3,5 1,3 1))");
+       rtdealloc(wkt);
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 2.8, FLT_EPSILON);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 3.0, 1.);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[1].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))");
+       rtdealloc(wkt);
+
+       for (i = 0; i < nPols; i++) lwgeom_free((LWGEOM *) gv[i].geom);
+       rtdealloc(gv);
+       cu_free_raster(rt);
+
+       /* Last test: There is no NODATA value (all values are valid) */
+       rt = fillRasterToPolygonize(0, 0.0);
+       /* We can check rt_raster_has_band here too */
+       CU_ASSERT(rt_raster_has_band(rt, 0));
+
+       nPols = 0;
+       gv = rt_raster_gdal_polygonize(rt, 0, TRUE, &nPols);
+
+       /*
+       for (i = 0; i < nPols; i++) {
+               wkt = lwgeom_to_text((const LWGEOM *) gv[i].geom);
+               printf("(i, val, geom) = (%d, %f, %s)\n", i, gv[i].val, wkt);
+               rtdealloc(wkt);
+       }
+       */
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 1.8, FLT_EPSILON);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[0].val, 2.0, 1.);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[0].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 1,3 2,2 2,2 3,1 3,1 6,2 6,2 7,3 7,3 8,5 8,5 6,3 6,3 3,4 3,5 3,5 1,3 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[1].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[1].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((3 3,3 6,6 6,6 3,3 3))");
+       rtdealloc(wkt);
+
+#ifdef GDALFPOLYGONIZE
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 2.8, FLT_EPSILON);
+#else
+       CU_ASSERT_DOUBLE_EQUAL(gv[2].val, 3.0, 1.);
+#endif
+
+       wkt = lwgeom_to_text((const LWGEOM *) gv[2].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((5 1,5 3,6 3,6 6,5 6,5 8,6 8,6 7,7 7,7 6,8 6,8 3,7 3,7 2,6 2,6 1,5 1))");
+       rtdealloc(wkt);
+
+       CU_ASSERT_DOUBLE_EQUAL(gv[3].val, 0.0, FLT_EPSILON);
+       wkt = lwgeom_to_text((const LWGEOM *) gv[3].geom);
+       CU_ASSERT_STRING_EQUAL(wkt, "POLYGON((0 0,0 9,9 9,9 0,0 0),(6 7,6 8,3 8,3 7,2 7,2 6,1 6,1 3,2 3,2 2,3 2,3 1,6 1,6 2,7 2,7 3,8 3,8 6,7 6,7 7,6 7))");
+       rtdealloc(wkt);
+
+       for (i = 0; i < nPols; i++) lwgeom_free((LWGEOM *) gv[i].geom);
+       rtdealloc(gv);
+       cu_free_raster(rt);
+}
+
+static void test_raster_to_gdal() {
+       rt_pixtype pixtype = PT_64BF;
+       rt_raster raster = NULL;
+       rt_band band = NULL;
+       uint32_t x;
+       uint32_t width = 100;
+       uint32_t y;
+       uint32_t height = 100;
+       int rtn = 0;
+       char srs[] = "PROJCS[\"unnamed\",GEOGCS[\"unnamed ellipse\",DATUM[\"unknown\",SPHEROID[\"unnamed\",6370997,0]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],PARAMETER[\"latitude_of_center\",45],PARAMETER[\"longitude_of_center\",-100],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1],AUTHORITY[\"EPSG\",\"2163\"]]";
+
+       uint64_t gdalSize;
+       uint8_t *gdal = NULL;
+
+       raster = rt_raster_new(width, height);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+
+       band = cu_add_band(raster, pixtype, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       rt_raster_set_offsets(raster, -500000, 600000);
+       rt_raster_set_scale(raster, 1000, -1000);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, (((double) x * y) + (x + y) + (x + y * x)) / (x + y + 1), NULL);
+               }
+       }
+
+       gdal = rt_raster_to_gdal(raster, srs, "GTiff", NULL, &gdalSize);
+       /*printf("gdalSize: %d\n", (int) gdalSize);*/
+       CU_ASSERT(gdalSize);
+
+       /*
+       FILE *fh = NULL;
+       fh = fopen("/tmp/out.tif", "w");
+       fwrite(gdal, sizeof(uint8_t), gdalSize, fh);
+       fclose(fh);
+       */
+
+       if (gdal) CPLFree(gdal);
+
+       cu_free_raster(raster);
+
+       raster = rt_raster_new(width, height);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+
+       band = cu_add_band(raster, pixtype, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       rt_raster_set_offsets(raster, -500000, 600000);
+       rt_raster_set_scale(raster, 1000, -1000);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, x, NULL);
+               }
+       }
+
+       /* add check that band isn't NODATA */
+       CU_ASSERT_EQUAL(rt_band_check_is_nodata(band), FALSE);
+
+       gdal = rt_raster_to_gdal(raster, srs, "PNG", NULL, &gdalSize);
+       /*printf("gdalSize: %d\n", (int) gdalSize);*/
+       CU_ASSERT(gdalSize);
+
+       if (gdal) CPLFree(gdal);
+
+       cu_free_raster(raster);
+}
+
+static void test_gdal_to_raster() {
+       rt_pixtype pixtype = PT_64BF;
+       rt_band band = NULL;
+
+       rt_raster raster;
+       rt_raster rast;
+       const uint32_t width = 100;
+       const uint32_t height = 100;
+       uint32_t x;
+       uint32_t y;
+       int v;
+       double values[width][height];
+       int rtn = 0;
+       double value;
+
+       GDALDriverH gddrv = NULL;
+       GDALDatasetH gdds = NULL;
+
+       raster = rt_raster_new(width, height);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+
+       band = cu_add_band(raster, pixtype, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       values[x][y] = (((double) x * y) + (x + y) + (x + y * x)) / (x + y + 1);
+                       rtn = rt_band_set_pixel(band, x, y, values[x][y], NULL);
+               }
+       }
+
+       gdds = rt_raster_to_gdal_mem(raster, NULL, NULL, NULL, 0, &gddrv);
+       CU_ASSERT(gddrv != NULL);
+       CU_ASSERT(gdds != NULL);
+       CU_ASSERT_EQUAL(GDALGetRasterXSize(gdds), width);
+       CU_ASSERT_EQUAL(GDALGetRasterYSize(gdds), height);
+
+       rast = rt_raster_from_gdal_dataset(gdds);
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(rast), 1);
+
+       band = rt_raster_get_band(rast, 0);
+       CU_ASSERT(band != NULL);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       rtn = rt_band_get_pixel(band, x, y, &value, NULL);
+                       CU_ASSERT_EQUAL(rtn, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(value, values[x][y], DBL_EPSILON);
+               }
+       }
+
+       GDALClose(gdds);
+       gdds = NULL;
+       gddrv = NULL;
+
+       cu_free_raster(rast);
+       cu_free_raster(raster);
+
+       raster = rt_raster_new(width, height);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+
+       pixtype = PT_8BSI;
+       band = cu_add_band(raster, pixtype, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       v = -127;
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       values[x][y] = v++;
+                       rtn = rt_band_set_pixel(band, x, y, values[x][y], NULL);
+                       if (v == 128)
+                               v = -127;
+               }
+       }
+
+       gdds = rt_raster_to_gdal_mem(raster, NULL, NULL, NULL, 0, &gddrv);
+       CU_ASSERT(gddrv != NULL);
+       CU_ASSERT(gdds != NULL);
+       CU_ASSERT_EQUAL(GDALGetRasterXSize(gdds), width);
+       CU_ASSERT_EQUAL(GDALGetRasterYSize(gdds), height);
+
+       rast = rt_raster_from_gdal_dataset(gdds);
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(rast), 1);
+
+       band = rt_raster_get_band(rast, 0);
+       CU_ASSERT(band != NULL);
+       CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_16BSI);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       rtn = rt_band_get_pixel(band, x, y, &value, NULL);
+                       CU_ASSERT_EQUAL(rtn, ES_NONE);
+                       CU_ASSERT_DOUBLE_EQUAL(value, values[x][y], 1.);
+               }
+       }
+
+       GDALClose(gdds);
+
+       cu_free_raster(rast);
+       cu_free_raster(raster);
+}
+
+static void test_gdal_warp() {
+       rt_pixtype pixtype = PT_64BF;
+       rt_band band = NULL;
+
+       rt_raster raster;
+       rt_raster rast;
+       uint32_t x;
+       uint32_t width = 100;
+       uint32_t y;
+       uint32_t height = 100;
+       int rtn = 0;
+       double value = 0;
+
+       char src_srs[] = "PROJCS[\"unnamed\",GEOGCS[\"unnamed ellipse\",DATUM[\"unknown\",SPHEROID[\"unnamed\",6370997,0]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],PARAMETER[\"latitude_of_center\",45],PARAMETER[\"longitude_of_center\",-100],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1],AUTHORITY[\"EPSG\",\"2163\"]]";
+
+       char dst_srs[] = "PROJCS[\"NAD83 / California Albers\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Albers_Conic_Equal_Area\"],PARAMETER[\"standard_parallel_1\",34],PARAMETER[\"standard_parallel_2\",40.5],PARAMETER[\"latitude_of_center\",0],PARAMETER[\"longitude_of_center\",-120],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",-4000000],AUTHORITY[\"EPSG\",\"3310\"],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]";
+
+       raster = rt_raster_new(width, height);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+
+       band = cu_add_band(raster, pixtype, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       rt_raster_set_offsets(raster, -500000, 600000);
+       rt_raster_set_scale(raster, 1000, -1000);
+
+       for (x = 0; x < width; x++) {
+               for (y = 0; y < height; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, (((double) x * y) + (x + y) + (x + y * x)) / (x + y + 1), NULL);
+               }
+       }
+
+       rast = rt_raster_gdal_warp(
+               raster,
+               src_srs, dst_srs,
+               NULL, NULL,
+               NULL, NULL,
+               NULL, NULL,
+               NULL, NULL,
+               NULL, NULL,
+               GRA_NearestNeighbour, -1
+       );
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rast), 122);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rast), 116);
+       CU_ASSERT_NOT_EQUAL(rt_raster_get_num_bands(rast), 0);
+
+       band = rt_raster_get_band(rast, 0);
+       CU_ASSERT(band != NULL);
+
+       CU_ASSERT(rt_band_get_hasnodata_flag(band));
+       rt_band_get_nodata(band, &value);
+       CU_ASSERT_DOUBLE_EQUAL(value, 0., DBL_EPSILON);
+
+       CU_ASSERT_EQUAL(rt_band_get_pixel(band, 0, 0, &value, NULL), ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(value, 0., DBL_EPSILON);
+
+       cu_free_raster(rast);
+       cu_free_raster(raster);
+}
+
+/* register tests */
+CU_TestInfo gdal_tests[] = {
+       PG_TEST(test_gdal_configured),
+       PG_TEST(test_gdal_drivers),
+       PG_TEST(test_gdal_rasterize),
+       PG_TEST(test_gdal_polygonize),
+       PG_TEST(test_raster_to_gdal),
+       PG_TEST(test_gdal_to_raster),
+       PG_TEST(test_gdal_warp),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo gdal_suite = {"gdal",  NULL,  NULL, gdal_tests};
diff --git a/raster/test/cunit/cu_mapalgebra.c b/raster/test/cunit/cu_mapalgebra.c
new file mode 100644 (file)
index 0000000..2e9d995
--- /dev/null
@@ -0,0 +1,880 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+typedef struct _callback_userargs_t* _callback_userargs;
+struct _callback_userargs_t {
+       uint16_t rasters;
+       uint32_t rows;
+       uint32_t columns;
+};
+
+/* callback for 1 raster, 0 distance, FIRST or SECOND or LAST or UNION or INTERSECTION */
+static int testRasterIterator1_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 0, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+       }
+       /* 4,4 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 4
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 24, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+       }
+       /* 1,1 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+       }
+       /* 2,2 */
+       else if (
+               arg->dst_pixel[0] == 2 &&
+               arg->dst_pixel[1] == 2
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 12, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+       }
+       /* 3,1 */
+       else if (
+               arg->dst_pixel[0] == 3 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 8, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+       }
+       /* 1,0 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 1, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+       }
+
+       return 1;
+}
+
+/* callback for 2 raster, 0 distance, UNION */
+static int testRasterIterator2_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 0, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+       /* 4,4 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 4
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 24, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 118, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 1,1 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 100, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 2,2 */
+       else if (
+               arg->dst_pixel[0] == 2 &&
+               arg->dst_pixel[1] == 2
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 12, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 106, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 3,1 */
+       else if (
+               arg->dst_pixel[0] == 3 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 8, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 102, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 1,0 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 1, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+       /* 1,3 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 3
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 16, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+       /* 5,0 */
+       else if (
+               arg->dst_pixel[0] == 5 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+
+       return 1;
+}
+
+/* callback for 2 raster, 0 distance, INTERSECTION */
+static int testRasterIterator3_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 100, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 0,3 */
+       else if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 3
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 21, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 115, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 3,0 */
+       else if (
+               arg->dst_pixel[0] == 3 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 9, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 103, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 3,3 */
+       else if (
+               arg->dst_pixel[0] == 3 &&
+               arg->dst_pixel[1] == 3
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 24, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 118, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 0,2 */
+       else if (
+               arg->dst_pixel[0] == 3 &&
+               arg->dst_pixel[1] == 3
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 16, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+
+       return 1;
+}
+
+/* callback for 2 raster, 0 distance, FIRST */
+static int testRasterIterator4_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 0, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+       /* 4,4 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 4
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 24, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 118, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 4,1 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 9, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 103, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 4,0 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 4, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+
+       return 1;
+}
+
+/* callback for 2 raster, 0 distance, SECOND or LAST */
+static int testRasterIterator5_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 100, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 4,4 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 4
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 124, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 4,1 */
+       else if (
+               arg->dst_pixel[0] == 4 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 1);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 109, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 0,2 */
+       else if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 2
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 16, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+
+       return 1;
+}
+
+/* callback for 2 raster, 0 distance, CUSTOM */
+static int testRasterIterator6_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 16, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+       /* 1,0 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 17, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 111, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 0,1 */
+       else if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 21, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 115, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+       /* 1,1 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 22, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][0][0], 116, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 0);
+       }
+
+       return 1;
+}
+
+/* callback for 2 raster, 1 distance, CUSTOM */
+static int testRasterIterator7_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata) {
+       _callback_userargs _userarg = (_callback_userargs) userarg;
+
+       /* check that we're getting what we expect from userarg */
+       CU_ASSERT_EQUAL(arg->rasters, _userarg->rasters);
+       CU_ASSERT_EQUAL(arg->rows, _userarg->rows);
+       CU_ASSERT_EQUAL(arg->columns, _userarg->columns);
+
+       /* 0,0 */
+       if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][1][1], 16, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][1][1], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][1][1], 1);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 10, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+       /* 1,0 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 0
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][1][1], 17, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][1][1], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][1][1], 111, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][1][1], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][2][2], 23, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][2][2], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][2][2], 117, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][2][2], 0);
+       }
+       /* 0,1 */
+       else if (
+               arg->dst_pixel[0] == 0 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][1][1], 21, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][1][1], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][1][1], 115, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][1][1], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[0][2][0], 1);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][2][0], 1);
+       }
+       /* 1,1 */
+       else if (
+               arg->dst_pixel[0] == 1 &&
+               arg->dst_pixel[1] == 1
+       ) {
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][1][1], 22, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][1][1], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[1][1][1], 116, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[1][1][1], 0);
+
+               CU_ASSERT_DOUBLE_EQUAL(arg->values[0][0][0], 16, DBL_EPSILON);
+               CU_ASSERT_EQUAL(arg->nodata[0][0][0], 0);
+
+               CU_ASSERT_EQUAL(arg->nodata[1][0][0], 1);
+       }
+
+       return 1;
+}
+
+static void test_raster_iterator() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_raster rast3;
+
+       int num = 2;
+
+       rt_raster rtn = NULL;
+       rt_band band;
+       int maxX = 5;
+       int maxY = 5;
+       rt_iterator itrset;
+       _callback_userargs userargs;
+       int noerr = 0;
+       int x = 0;
+       int y = 0;
+
+       rast1 = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast1 != NULL);
+
+       rt_raster_set_offsets(rast1, 0, 0);
+       rt_raster_set_scale(rast1, 1, -1);
+
+       band = cu_add_band(rast1, PT_32BUI, 1, 6);
+       CU_ASSERT(band != NULL);
+
+       for (y = 0; y < maxY; y++) {
+               for (x = 0; x < maxX; x++) {
+                       rt_band_set_pixel(band, x, y, x + (y * maxX), NULL);
+               }
+       }
+
+       rast2 = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast2 != NULL);
+
+       rt_raster_set_offsets(rast2, 1, -1);
+       rt_raster_set_scale(rast2, 1, -1);
+
+       band = cu_add_band(rast2, PT_32BUI, 1, 110);
+       CU_ASSERT(band != NULL);
+
+       for (y = 0; y < maxY; y++) {
+               for (x = 0; x < maxX; x++) {
+                       rt_band_set_pixel(band, x, y, (x + (y * maxX)) + 100, NULL);
+               }
+       }
+
+       rast3 = rt_raster_new(2, 2);
+       CU_ASSERT(rast3 != NULL);
+
+       rt_raster_set_offsets(rast3, 1, -3);
+       rt_raster_set_scale(rast3, 1, -1);
+
+       /* allocate user args */
+       userargs = rtalloc(sizeof(struct _callback_userargs_t));
+       CU_ASSERT(userargs != NULL);
+
+       /* allocate itrset */
+       itrset = rtalloc(sizeof(struct rt_iterator_t) * num);
+       CU_ASSERT(itrset != NULL);
+       itrset[0].raster = rast1;
+       itrset[0].nband = 0;
+       itrset[0].nbnodata = 1;
+       itrset[1].raster = rast2;
+       itrset[1].nband = 0;
+       itrset[1].nbnodata = 1;
+
+       /* 1 raster, 0 distance, FIRST or SECOND or LAST or UNION or INTERSECTION */
+       userargs->rasters = 1;
+       userargs->rows = 1;
+       userargs->columns = 1;
+
+       noerr = rt_raster_iterator(
+               itrset, 1,
+               ET_INTERSECTION, NULL,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator1_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 5);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 5);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 1 raster, 0 distance, FIRST or SECOND or LAST or UNION or INTERSECTION */
+       userargs->rasters = 1;
+       userargs->rows = 1;
+       userargs->columns = 1;
+
+       noerr = rt_raster_iterator(
+               itrset, 1,
+               ET_UNION, NULL,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator1_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 5);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 5);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 2 raster, 0 distance, UNION */
+       userargs->rasters = 2;
+       userargs->rows = 1;
+       userargs->columns = 1;
+
+       noerr = rt_raster_iterator(
+               itrset, 2,
+               ET_UNION, NULL,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator2_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 6);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 6);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 2 raster, 0 distance, INTERSECTION */
+       noerr = rt_raster_iterator(
+               itrset, 2,
+               ET_INTERSECTION, NULL,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator3_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 4);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 4);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 2 raster, 0 distance, FIRST */
+       noerr = rt_raster_iterator(
+               itrset, 2,
+               ET_FIRST, NULL,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator4_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 5);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 5);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 2 raster, 0 distance, LAST or SECOND */
+       noerr = rt_raster_iterator(
+               itrset, 2,
+               ET_LAST, NULL,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator5_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 5);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 5);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 2 raster, 0 distance, CUSTOM */
+       noerr = rt_raster_iterator(
+               itrset, 2,
+               ET_CUSTOM, rast3,
+               PT_32BUI,
+               1, 0,
+               0, 0,
+               userargs,
+               testRasterIterator6_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 2);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 2);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), -3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       /* 2 raster, 1 distance, CUSTOM */
+       userargs->rasters = 2;
+       userargs->rows = 3;
+       userargs->columns = 3;
+
+       noerr = rt_raster_iterator(
+               itrset, 2,
+               ET_CUSTOM, rast3,
+               PT_32BUI,
+               1, 0,
+               1, 1,
+               userargs,
+               testRasterIterator7_callback,
+               &rtn
+       );
+       CU_ASSERT_EQUAL(noerr, ES_NONE);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rtn), 2);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rtn), 2);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rtn), -3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(rtn), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(rtn), -1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(rtn), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rtn), 0);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+       rtn = NULL;
+
+       rtdealloc(userargs);
+       rtdealloc(itrset);
+
+       cu_free_raster(rast1);
+       cu_free_raster(rast2);
+       cu_free_raster(rast3);
+
+       if (rtn != NULL) cu_free_raster(rtn);
+}
+
+static void test_band_reclass() {
+       rt_reclassexpr *exprset;
+
+       rt_raster raster;
+       rt_band band;
+       uint16_t x;
+       uint16_t y;
+       double nodata;
+       int cnt = 2;
+       int i = 0;
+       int rtn;
+       rt_band newband;
+       double val;
+
+       raster = rt_raster_new(100, 10);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+       band = cu_add_band(raster, PT_16BUI, 0, 0);
+       CU_ASSERT(band != NULL);
+       rt_band_set_nodata(band, 0, NULL);
+
+       for (x = 0; x < 100; x++) {
+               for (y = 0; y < 10; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, x * y + (x + y), NULL);
+               }
+       }
+
+       rt_band_get_nodata(band, &nodata);
+       CU_ASSERT_DOUBLE_EQUAL(nodata, 0, DBL_EPSILON);
+
+       exprset = rtalloc(cnt * sizeof(rt_reclassexpr));
+       CU_ASSERT(exprset != NULL);
+
+       for (i = 0; i < cnt; i++) {
+               exprset[i] = rtalloc(sizeof(struct rt_reclassexpr_t));
+               CU_ASSERT(exprset[i] != NULL);
+
+               if (i == 0) {
+                       /* nodata */
+                       exprset[i]->src.min = 0;
+                       exprset[i]->src.inc_min = 0;
+                       exprset[i]->src.exc_min = 0;
+
+                       exprset[i]->src.max = 0;
+                       exprset[i]->src.inc_max = 0;
+                       exprset[i]->src.exc_max = 0;
+
+                       exprset[i]->dst.min = 0;
+                       exprset[i]->dst.max = 0;
+               }
+               else {
+                       /* range */
+                       exprset[i]->src.min = 0;
+                       exprset[i]->src.inc_min = 0;
+                       exprset[i]->src.exc_min = 0;
+
+                       exprset[i]->src.max = 1000;
+                       exprset[i]->src.inc_max = 1;
+                       exprset[i]->src.exc_max = 0;
+
+                       exprset[i]->dst.min = 1;
+                       exprset[i]->dst.max = 255;
+               }
+       }
+
+       newband = rt_band_reclass(band, PT_8BUI, 0, 0, exprset, cnt);
+       CU_ASSERT(newband != NULL);
+
+       rtn = rt_band_get_pixel(newband, 0, 0, &val, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+       rtn = rt_band_get_pixel(newband, 49, 5, &val, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(val, 77, DBL_EPSILON);
+
+       rtn = rt_band_get_pixel(newband, 99, 9, &val, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(val, 255, DBL_EPSILON);
+
+       for (i = cnt - 1; i >= 0; i--) rtdealloc(exprset[i]);
+       rtdealloc(exprset);
+       cu_free_raster(raster);
+
+       rt_band_destroy(newband);
+}
+
+/* register tests */
+CU_TestInfo mapalgebra_tests[] = {
+       PG_TEST(test_raster_iterator),
+       PG_TEST(test_band_reclass),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo mapalgebra_suite = {"mapalgebra",  NULL,  NULL, mapalgebra_tests};
diff --git a/raster/test/cunit/cu_pixtype.c b/raster/test/cunit/cu_pixtype.c
new file mode 100644 (file)
index 0000000..f89c3e9
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_pixtype_size() {
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_1BB), 1);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_2BUI), 1);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_4BUI), 1);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_8BUI), 1);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_8BSI), 1);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_16BUI), 2);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_16BSI), 2);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_32BUI), 4);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_32BSI), 4);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_32BF), 4);
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_64BF), 8);
+
+       CU_ASSERT_EQUAL(rt_pixtype_size(PT_END), -1);
+}
+
+static void test_pixtype_alignment() {
+       /* rt_pixtype_alignment() just forwards to rt_pixtype_size() */
+}
+
+static void test_pixtype_name() {
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_1BB), "1BB");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_2BUI), "2BUI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_4BUI), "4BUI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_8BUI), "8BUI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_8BSI), "8BSI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_16BUI), "16BUI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_16BSI), "16BSI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_32BUI), "32BUI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_32BSI), "32BSI");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_32BF), "32BF");
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_64BF), "64BF");
+
+       CU_ASSERT_STRING_EQUAL(rt_pixtype_name(PT_END), "Unknown");
+}
+
+static void test_pixtype_index_from_name() {
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("1BB"), PT_1BB);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("2BUI"), PT_2BUI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("4BUI"), PT_4BUI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("8BUI"), PT_8BUI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("8BSI"), PT_8BSI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("16BUI"), PT_16BUI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("16BSI"), PT_16BSI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("32BUI"), PT_32BUI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("32BSI"), PT_32BSI);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("32BF"), PT_32BF);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("64BF"), PT_64BF);
+
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("END"), PT_END);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("1bb"), PT_END);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("1bB"), PT_END);
+       CU_ASSERT_EQUAL(rt_pixtype_index_from_name("3BUI"), PT_END);
+}
+
+static void test_pixtype_get_min_value() {
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_1BB), rt_util_clamp_to_1BB((double) CHAR_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_2BUI), rt_util_clamp_to_2BUI((double) CHAR_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_4BUI), rt_util_clamp_to_4BUI((double) CHAR_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_8BUI), rt_util_clamp_to_8BUI((double) CHAR_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_8BSI), rt_util_clamp_to_8BSI((double) SCHAR_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_16BUI), rt_util_clamp_to_16BUI((double) SHRT_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_16BSI), rt_util_clamp_to_16BSI((double) SHRT_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_32BUI), rt_util_clamp_to_32BUI((double) INT_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_32BSI), rt_util_clamp_to_32BSI((double) INT_MIN), DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_32BF), -FLT_MAX, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_64BF), -DBL_MAX, DBL_EPSILON);
+
+       CU_ASSERT_DOUBLE_EQUAL(rt_pixtype_get_min_value(PT_END), rt_util_clamp_to_8BUI((double) CHAR_MIN), DBL_EPSILON);
+}
+
+static void test_pixtype_compare_clamped_values() {
+       int isequal = 0;
+
+       /* 1BB */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_1BB, 0, 0, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_1BB, 0, 1, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_1BB, 1, 0, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_1BB, 1, 1, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_1BB, 0, 2, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_1BB, 0, -9999, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 2BUI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, 0, 0, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, 0, 1, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, 0, 3, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, 1, 1, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, 3, 2, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, 4, 0, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_2BUI, -1, 0, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 4BUI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_4BUI, 10, 10, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_4BUI, 10, 1, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_4BUI, 0, 15, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_4BUI, 15, 15, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_4BUI, 0, 16, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_4BUI, 16, 15, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 8BUI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BUI, 155, 155, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BUI, 155, 255, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BUI, 0, 155, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BUI, -1, -1, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BUI, 0, -1, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BUI, 256, 255, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 8BSI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, 120, 120, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, -120, 120, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, -10, -10, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, -128, -128, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, -128, 128, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, -129, -128, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_8BSI, 129, 128, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 16BUI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BUI, 65535, 65535, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BUI, 0, 0, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BUI, 12345, 12344, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BUI, 0, 65535, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BUI, 65536, -1, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BUI, -9999, 0, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 16BSI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BSI, -32000, -32000, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BSI, -32767, -32767, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BSI, 32767, 32768, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BSI, 32766, 32768, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BSI, 0, -32768, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_16BSI, 32767, -32767, &isequal), ES_NONE);
+       CU_ASSERT(!isequal);
+
+       /* 32BUI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_32BUI, 4294967295UL, 4294967295UL, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_32BUI, 4294967296ULL, 4294967295UL, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 32BSI */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_32BSI, 2147483647, 2147483647, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_32BSI, 2147483648UL, 2147483647, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 32BF */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_32BF, 65535.5, 65535.5, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_32BF, 0.0060000000521540, 0.0060000000521540, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       /* 64BF */
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_64BF, 65535.5, 65535.5, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+       CU_ASSERT_EQUAL(rt_pixtype_compare_clamped_values(PT_64BF, 0.0060000000521540, 0.0060000000521540, &isequal), ES_NONE);
+       CU_ASSERT(isequal);
+
+       CU_ASSERT_NOT_EQUAL(rt_pixtype_compare_clamped_values(PT_END, 1, 1, &isequal), ES_NONE);
+}
+
+/* register tests */
+CU_TestInfo pixtype_tests[] = {
+       PG_TEST(test_pixtype_size),
+       PG_TEST(test_pixtype_alignment),
+       PG_TEST(test_pixtype_name),
+       PG_TEST(test_pixtype_index_from_name),
+       PG_TEST(test_pixtype_get_min_value),
+       PG_TEST(test_pixtype_compare_clamped_values),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo pixtype_suite = {"pixtype",  NULL,  NULL, pixtype_tests};
diff --git a/raster/test/cunit/cu_raster_basics.c b/raster/test/cunit/cu_raster_basics.c
new file mode 100644 (file)
index 0000000..363a1e2
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_raster_new() {
+       rt_raster raster = NULL;
+
+       raster = rt_raster_new(0, 0);
+       CU_ASSERT(raster != NULL);
+       cu_free_raster(raster);
+
+       raster = rt_raster_new(1, 1);
+       CU_ASSERT(raster != NULL);
+       cu_free_raster(raster);
+
+       raster = rt_raster_new(10, 10);
+       CU_ASSERT(raster != NULL);
+       cu_free_raster(raster);
+}
+
+static void test_raster_empty() {
+       rt_raster raster = NULL;
+
+       /* check that raster is empty */
+       raster = rt_raster_new(0, 0);
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT(rt_raster_is_empty(raster));
+       cu_free_raster(raster);
+
+       /* create raster */
+       raster = rt_raster_new(1, 1);
+       CU_ASSERT(raster != NULL);
+
+       /* check that raster is not empty */
+       CU_ASSERT(!rt_raster_is_empty(raster));
+
+       cu_free_raster(raster);
+}
+
+static void test_raster_metadata() {
+       rt_raster raster = NULL;
+
+       /* create raster */
+       raster = rt_raster_new(5, 5);
+       CU_ASSERT(raster != NULL);
+
+       /* # of bands */
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 0);
+
+       /* has bands */
+       CU_ASSERT(!rt_raster_has_band(raster, 1));
+
+       /* upper-left corner */
+       rt_raster_set_offsets(raster, 30, -70);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 30, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), -70, DBL_EPSILON);
+
+       /* scale */
+       rt_raster_set_scale(raster, 10, -10);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 10, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), -10, DBL_EPSILON);
+
+       /* skew */
+       rt_raster_set_skews(raster, 0.0001, -0.05);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 0.0001, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), -0.05, DBL_EPSILON);
+
+       /* srid */
+       rt_raster_set_srid(raster, 4326);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 4326);
+       rt_raster_set_srid(raster, 4269);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 4269);
+
+       cu_free_raster(raster);
+}
+
+static void test_raster_clone() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band;
+
+       int maxX = 5;
+       int maxY = 5;
+       double gt[6];
+
+       rast1 = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast1 != NULL);
+
+       rt_raster_set_offsets(rast1, 0, 0);
+       rt_raster_set_scale(rast1, 1, -1);
+       rt_raster_set_srid(rast1, 4326);
+
+       band = cu_add_band(rast1, PT_32BUI, 1, 6);
+       CU_ASSERT(band != NULL);
+
+       /* clone without bands */
+       rast2 = rt_raster_clone(rast1, 0);
+       CU_ASSERT(rast2 != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(rast2), 0);
+
+       rt_raster_get_geotransform_matrix(rast2, gt);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(rast2), 4326);
+       CU_ASSERT_DOUBLE_EQUAL(gt[0], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(gt[1], 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(gt[2], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(gt[3], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(gt[4], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(gt[5], -1, DBL_EPSILON);
+
+       cu_free_raster(rast2);
+
+       /* clone with bands */
+       rast2 = rt_raster_clone(rast1, 1);
+       CU_ASSERT(rast2 != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(rast2), 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_from_band() {
+       uint32_t bandNums[] = {1,3};
+       int lenBandNums = 2;
+       rt_raster raster;
+       rt_raster rast;
+       rt_band band;
+       uint32_t xmax = 100;
+       uint32_t ymax = 100;
+       uint32_t x;
+
+       raster = rt_raster_new(xmax, ymax);
+       CU_ASSERT(raster != NULL);
+
+       for (x = 0; x < 5; x++) {
+               band = cu_add_band(raster, PT_32BUI, 0, 0);
+               CU_ASSERT(band != NULL);
+               rt_band_set_nodata(band, 0, NULL);
+       }
+
+       rast = rt_raster_from_band(raster, bandNums, lenBandNums);
+       CU_ASSERT(rast != NULL);
+
+       CU_ASSERT(!rt_raster_is_empty(rast));
+       CU_ASSERT(rt_raster_has_band(rast, 1));
+
+       cu_free_raster(rast);
+       cu_free_raster(raster);
+}
+
+static void test_raster_replace_band() {
+       rt_raster raster;
+       rt_band band;
+       rt_band rband;
+       void* mem;
+       size_t datasize;
+       uint16_t width;
+       uint16_t height;
+       double nodata;
+
+       raster = rt_raster_new(10, 10);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+       band = cu_add_band(raster, PT_8BUI, 0, 0);
+       CU_ASSERT(band != NULL);
+       band = cu_add_band(raster, PT_8BUI, 1, 255);
+       CU_ASSERT(band != NULL);
+
+       width = rt_raster_get_width(raster);
+       height = rt_raster_get_height(raster);
+
+       datasize = rt_pixtype_size(PT_8BUI) * width * height;
+       mem = rtalloc(datasize);
+       band = rt_band_new_inline(width, height, PT_8BUI, 1, 1, mem);
+       CU_ASSERT(band != NULL);
+
+       rband = rt_raster_replace_band(raster, band, 0);
+       CU_ASSERT(rband != NULL);
+       rt_band_get_nodata(rt_raster_get_band(raster, 0), &nodata);
+       CU_ASSERT_DOUBLE_EQUAL(nodata, 1, DBL_EPSILON);
+
+       rt_band_destroy(rband);
+       cu_free_raster(raster);
+}
+
+/* register tests */
+CU_TestInfo raster_basics_tests[] = {
+       PG_TEST(test_raster_new),
+       PG_TEST(test_raster_empty),
+       PG_TEST(test_raster_metadata),
+       PG_TEST(test_raster_clone),
+       PG_TEST(test_raster_from_band),
+       PG_TEST(test_raster_replace_band),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo raster_basics_suite = {"raster_basics",  NULL,  NULL, raster_basics_tests};
diff --git a/raster/test/cunit/cu_raster_geometry.c b/raster/test/cunit/cu_raster_geometry.c
new file mode 100644 (file)
index 0000000..7d9ff15
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_raster_convex_hull() {
+       rt_raster raster = NULL;
+       LWPOLY *convexhull = NULL;
+       POINTARRAY *ring = NULL;
+       POINT4D pt;
+
+       /* create raster */
+       raster = rt_raster_new(256, 256);
+       CU_ASSERT(raster != NULL);
+
+       rt_raster_set_offsets(raster, 0.5, 0.5);
+       rt_raster_set_scale(raster, 1, 1);
+       rt_raster_set_skews(raster, 4, 5);
+
+       convexhull = rt_raster_get_convex_hull(raster);
+       CU_ASSERT_EQUAL(convexhull->srid, rt_raster_get_srid(raster));
+       CU_ASSERT_EQUAL(convexhull->nrings, 1);
+
+       ring = convexhull->rings[0];
+       CU_ASSERT(ring != NULL);
+       CU_ASSERT_EQUAL(ring->npoints, 5);
+
+       getPoint4d_p(ring, 0, &pt);
+       CU_ASSERT_DOUBLE_EQUAL(pt.x, 0.5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(pt.y, 0.5, DBL_EPSILON);
+
+       getPoint4d_p(ring, 1, &pt);
+       CU_ASSERT_DOUBLE_EQUAL(pt.x, 256.5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(pt.y, 1280.5, DBL_EPSILON);
+
+       getPoint4d_p(ring, 2, &pt);
+       CU_ASSERT_DOUBLE_EQUAL(pt.x, 1280.5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(pt.y, 1536.5, DBL_EPSILON);
+
+       getPoint4d_p(ring, 3, &pt);
+       CU_ASSERT_DOUBLE_EQUAL(pt.x, 1024.5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(pt.y, 256.5, DBL_EPSILON);
+
+       getPoint4d_p(ring, 4, &pt);
+       CU_ASSERT_DOUBLE_EQUAL(pt.x, 0.5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(pt.y, 0.5, DBL_EPSILON);
+
+       lwpoly_free(convexhull);
+       cu_free_raster(raster);
+}
+
+static char *
+lwgeom_to_text(const LWGEOM *lwgeom) {
+       char *wkt;
+       size_t wkt_size;
+
+       wkt = lwgeom_to_wkt(lwgeom, WKT_ISO, DBL_DIG, &wkt_size);
+
+       return wkt;
+}
+
+static void test_raster_surface() {
+       rt_raster rast;
+       rt_band band;
+       const int maxX = 5;
+       const int maxY = 5;
+       int x, y;
+       char *wkt = NULL;
+       LWMPOLY *mpoly = NULL;
+       int err;
+
+       rast = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast != NULL);
+
+       rt_raster_set_offsets(rast, 0, 0);
+       rt_raster_set_scale(rast, 1, -1);
+
+       band = cu_add_band(rast, PT_32BUI, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       for (y = 0; y < maxY; y++) {
+               for (x = 0; x < maxX; x++) {
+                       rt_band_set_pixel(band, x, y, 1, NULL);
+               }
+       }
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((0 0,0 -5,5 -5,5 0,0 0)))");
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       /* 0,0 NODATA */
+       rt_band_set_pixel(band, 0, 0, 0, NULL);
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 0,1 -1,0 -1,0 -5,4 -5,5 -5,5 0,1 0)))");
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       /* plus 1,1 NODATA */
+       rt_band_set_pixel(band, 1, 1, 0, NULL);
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 0,1 -1,0 -1,0 -5,4 -5,5 -5,5 0,1 0),(1 -1,1 -2,2 -2,2 -1,1 -1)))");
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       /* plus 2,2 NODATA */
+       rt_band_set_pixel(band, 2, 2, 0, NULL);
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+#if POSTGIS_GEOS_VERSION >= 33
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 -1,1 0,5 0,5 -5,4 -5,0 -5,0 -1,1 -1),(1 -1,1 -2,2 -2,2 -1,1 -1),(2 -2,2 -3,3 -3,3 -2,2 -2)))");
+#else
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 0,1 -1,0 -1,0 -5,4 -5,5 -5,5 0,1 0),(1 -1,1 -2,2 -2,2 -3,3 -3,3 -2,2 -2,2 -1,1 -1)))");
+#endif
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       /* plus 3,3 NODATA */
+       rt_band_set_pixel(band, 3, 3, 0, NULL);
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+#if POSTGIS_GEOS_VERSION >= 33
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 -1,1 0,5 0,5 -5,4 -5,0 -5,0 -1,1 -1),(1 -1,1 -2,2 -2,2 -1,1 -1),(2 -2,2 -3,3 -3,3 -2,2 -2),(3 -3,3 -4,4 -4,4 -3,3 -3)))");
+#else
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 0,1 -1,0 -1,0 -5,4 -5,5 -5,5 0,1 0),(1 -1,1 -2,2 -2,2 -3,3 -3,3 -4,4 -4,4 -3,3 -3,3 -2,2 -2,2 -1,1 -1)))");
+#endif
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       /* plus 4,4 NODATA */
+       rt_band_set_pixel(band, 4, 4, 0, NULL);
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((4 -4,4 -5,0 -5,0 -1,1 -1,1 -2,2 -2,2 -3,3 -3,3 -4,4 -4)),((1 -1,1 0,5 0,5 -4,4 -4,4 -3,3 -3,3 -2,2 -2,2 -1,1 -1)))");
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       /* a whole lot more NODATA */
+       rt_band_set_pixel(band, 4, 0, 0, NULL);
+       rt_band_set_pixel(band, 3, 1, 0, NULL);
+       rt_band_set_pixel(band, 1, 3, 0, NULL);
+       rt_band_set_pixel(band, 0, 4, 0, NULL);
+
+       err = rt_raster_surface(rast, 0, &mpoly);
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(mpoly != NULL);
+       wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly));
+       CU_ASSERT_STRING_EQUAL(wkt, "MULTIPOLYGON(((1 -4,2 -4,2 -3,3 -3,3 -4,4 -4,4 -5,3 -5,1 -5,1 -4)),((1 -4,0 -4,0 -1,1 -1,1 -2,2 -2,2 -3,1 -3,1 -4)),((3 -2,4 -2,4 -1,5 -1,5 -4,4 -4,4 -3,3 -3,3 -2)),((3 -2,2 -2,2 -1,1 -1,1 0,4 0,4 -1,3 -1,3 -2)))");
+       rtdealloc(wkt);
+       lwmpoly_free(mpoly);
+       mpoly = NULL;
+
+       cu_free_raster(rast);
+}
+
+static void test_raster_pixel_as_polygon() {
+       rt_raster rast;
+       rt_band band;
+       uint32_t x, y;
+       int rtn;
+       const int maxX = 10;
+       const int maxY = 10;
+       LWPOLY *poly = NULL;
+
+       rast = rt_raster_new(maxX, maxY);
+       CU_ASSERT(rast != NULL);
+
+       band = cu_add_band(rast, PT_32BUI, 1, 0);
+       CU_ASSERT(band != NULL);
+
+       for (x = 0; x < maxX; x++) {
+               for (y = 0; y < maxY; y++) {
+                       rtn = rt_band_set_pixel(band, x, y, 1, NULL);
+               }
+       }
+
+       rt_band_set_pixel(band, 0, 0, 0, NULL);
+       rt_band_set_pixel(band, 3, 0, 0, NULL);
+       rt_band_set_pixel(band, 6, 0, 0, NULL);
+       rt_band_set_pixel(band, 9, 0, 0, NULL);
+       rt_band_set_pixel(band, 1, 2, 0, NULL);
+       rt_band_set_pixel(band, 4, 2, 0, NULL);
+       rt_band_set_pixel(band, 7, 2, 0, NULL);
+       rt_band_set_pixel(band, 2, 4, 0, NULL);
+       rt_band_set_pixel(band, 5, 4, 0, NULL);
+       rt_band_set_pixel(band, 8, 4, 0, NULL);
+       rt_band_set_pixel(band, 0, 6, 0, NULL);
+       rt_band_set_pixel(band, 3, 6, 0, NULL);
+       rt_band_set_pixel(band, 6, 6, 0, NULL);
+       rt_band_set_pixel(band, 9, 6, 0, NULL);
+       rt_band_set_pixel(band, 1, 8, 0, NULL);
+       rt_band_set_pixel(band, 4, 8, 0, NULL);
+       rt_band_set_pixel(band, 7, 8, 0, NULL);
+
+       poly = rt_raster_pixel_as_polygon(rast, 1, 1);
+       CU_ASSERT(poly != NULL);
+       lwpoly_free(poly);
+
+       cu_free_raster(rast);
+}
+
+/* register tests */
+CU_TestInfo raster_geometry_tests[] = {
+       /* TODO: rt_raster_envelope()
+       PG_TEST(test_raster_envelope),
+       */
+       PG_TEST(test_raster_convex_hull),
+       PG_TEST(test_raster_surface),
+       PG_TEST(test_raster_pixel_as_polygon),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo raster_geometry_suite = {"raster_geometry",  NULL,  NULL, raster_geometry_tests};
diff --git a/raster/test/cunit/cu_raster_misc.c b/raster/test/cunit/cu_raster_misc.c
new file mode 100644 (file)
index 0000000..4f90ea6
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_raster_cell_to_geopoint() {
+       rt_raster raster;
+       int rtn;
+       double xw, yw;
+       double gt[6] = {-128.604911499087763, 0.002424431085498, 0, 53.626968388905752, 0, -0.002424431085498};
+
+       raster = rt_raster_new(1, 1);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+       rt_raster_set_srid(raster, 4326);
+       rt_raster_set_geotransform_matrix(raster, gt);
+
+       rtn = rt_raster_cell_to_geopoint(raster, 0, 0, &xw, &yw, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(xw, gt[0], DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(yw, gt[3], DBL_EPSILON);
+
+       cu_free_raster(raster);
+}
+
+static void test_raster_geopoint_to_cell() {
+       rt_raster raster;
+       int rtn;
+       double xr, yr;
+       double gt[6] = {-128.604911499087763, 0.002424431085498, 0, 53.626968388905752, 0, -0.002424431085498};
+
+       raster = rt_raster_new(1, 1);
+       CU_ASSERT(raster != NULL); /* or we're out of virtual memory */
+       rt_raster_set_srid(raster, 4326);
+       rt_raster_set_geotransform_matrix(raster, gt);
+
+       rtn = rt_raster_geopoint_to_cell(raster, gt[0], gt[3], &xr, &yr, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_DOUBLE_EQUAL(xr, 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(yr, 0, DBL_EPSILON);
+
+       cu_free_raster(raster);
+}
+
+static void test_raster_from_two_rasters() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_raster rast = NULL;
+       int err;
+       double offset[4] = {0.};
+
+       rast1 = rt_raster_new(4, 4);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -2, -2);
+
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_FIRST,
+               &rast,
+               offset
+       );
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rast), 4);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rast), 4);
+       CU_ASSERT_DOUBLE_EQUAL(offset[0], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[1], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[2], 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[3], 2, DBL_EPSILON);
+       cu_free_raster(rast);
+
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_SECOND,
+               &rast,
+               offset
+       );
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rast), 2);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rast), 2);
+       CU_ASSERT_DOUBLE_EQUAL(offset[0], -2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[1], -2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[2], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[3], 0, DBL_EPSILON);
+       cu_free_raster(rast);
+
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_INTERSECTION,
+               &rast,
+               offset
+       );
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rast), 2);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rast), 2);
+       CU_ASSERT_DOUBLE_EQUAL(offset[0], -2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[1], -2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[2], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[3], 0, DBL_EPSILON);
+       cu_free_raster(rast);
+
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_UNION,
+               &rast,
+               offset
+       );
+       CU_ASSERT_EQUAL(err, ES_NONE);
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rast), 4);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rast), 4);
+       CU_ASSERT_DOUBLE_EQUAL(offset[0], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[1], 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[2], 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(offset[3], 2, DBL_EPSILON);
+       cu_free_raster(rast);
+
+       rt_raster_set_scale(rast2, 1, 0.1);
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_UNION,
+               &rast,
+               offset
+       );
+       CU_ASSERT_NOT_EQUAL(err, ES_NONE);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       rt_raster_set_srid(rast2, 9999);
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_UNION,
+               &rast,
+               offset
+       );
+       CU_ASSERT_NOT_EQUAL(err, ES_NONE);
+       rt_raster_set_srid(rast2, 0);
+
+       rt_raster_set_skews(rast2, -1, 1);
+       err = rt_raster_from_two_rasters(
+               rast1, rast2,
+               ET_UNION,
+               &rast,
+               offset
+       );
+       CU_ASSERT_NOT_EQUAL(err, ES_NONE);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_compute_skewed_raster() {
+       rt_envelope extent;
+       rt_raster rast;
+       double skew[2] = {0.25, 0.25};
+       double scale[2] = {1, -1};
+
+       extent.MinX = 0;
+       extent.MaxY = 0;
+       extent.MaxX = 2;
+       extent.MinY = -2;
+       extent.UpperLeftX = extent.MinX;
+       extent.UpperLeftY = extent.MaxY;
+
+       rast = rt_raster_compute_skewed_raster(
+               extent,
+               skew,
+               scale,
+               0
+       );
+
+       CU_ASSERT(rast != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_width(rast), 2);
+       CU_ASSERT_EQUAL(rt_raster_get_height(rast), 3);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(rast), -0.5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(rast), 0, DBL_EPSILON);
+
+       cu_free_raster(rast);
+}
+
+/* register tests */
+CU_TestInfo raster_misc_tests[] = {
+       PG_TEST(test_raster_cell_to_geopoint),
+       PG_TEST(test_raster_geopoint_to_cell),
+       PG_TEST(test_raster_from_two_rasters),
+       PG_TEST(test_raster_compute_skewed_raster),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo raster_misc_suite = {"raster_misc",  NULL,  NULL, raster_misc_tests};
diff --git a/raster/test/cunit/cu_raster_wkb.c b/raster/test/cunit/cu_raster_wkb.c
new file mode 100644 (file)
index 0000000..516b9c1
--- /dev/null
@@ -0,0 +1,816 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ * Copyright (C) 2009  Sandro Santilli <strk@keybit.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_raster_wkb() {
+       /* will use default allocators and message handlers */
+       rt_raster raster = NULL;
+       const char *hexwkb = NULL;
+       const char *out = NULL;
+       uint32_t len = 0;
+       int i = 0;
+
+       /* ------------------------------------------------------ */
+       /* No bands, 7x8 - little endian                          */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"01"               /* little endian (uint8 ndr) */
+"0000"             /* version (uint16 0) */
+"0000"             /* nBands (uint16 0) */
+"000000000000F03F" /* scaleX (float64 1) */
+"0000000000000040" /* scaleY (float64 2) */
+"0000000000000840" /* ipX (float64 3) */
+"0000000000001040" /* ipY (float64 4) */
+"0000000000001440" /* skewX (float64 5) */
+"0000000000001840" /* skewY (float64 6) */
+"0A000000"         /* SRID (int32 10) */
+"0700"             /* width (uint16 7) */
+"0800"             /* height (uint16 8) */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 0);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 7);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 8);
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %d\n", strlen(hexwkb));
+       printf("out hexwkb len: %d\n", len);
+       printf(" in hexwkb: %s\n", hexwkb);
+       printf("out hexwkb: %s\n", out);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian...
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+       free((/*no const*/ void*)out);
+
+       {
+               void *serialized;
+               rt_raster rast2;
+
+               serialized = rt_raster_serialize(raster);
+               rast2 = rt_raster_deserialize(serialized, FALSE);
+
+               rt_raster_destroy(rast2);
+               free(serialized);
+       }
+
+       rt_raster_destroy(raster);
+
+       /* ------------------------------------------------------ */
+       /* No bands, 7x8 - big endian                             */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"00"               /* big endian (uint8 xdr) */
+"0000"             /* version (uint16 0) */
+"0000"             /* nBands (uint16 0) */
+"3FF0000000000000" /* scaleX (float64 1) */
+"4000000000000000" /* scaleY (float64 2) */
+"4008000000000000" /* ipX (float64 3) */
+"4010000000000000" /* ipY (float64 4) */
+"4014000000000000" /* skewX (float64 5) */
+"4018000000000000" /* skewY (float64 6) */
+"0000000A"         /* SRID (int32 10) */
+"0007"             /* width (uint16 7) */
+"0008"             /* height (uint16 8) */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 0);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 7);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 8);
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+       printf(" in hexwkb: %s\n", hexwkb);
+       printf("out hexwkb: %s\n", out);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian...
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       rt_raster_destroy(raster);
+       free((/*no const*/ void*)out);
+
+       /* ------------------------------------------------------ */
+       /* 1x1, little endian, band0(1bb)                         */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"01"               /* little endian (uint8 ndr) */
+"0000"             /* version (uint16 0) */
+"0100"             /* nBands (uint16 1) */
+"000000000000F03F" /* scaleX (float64 1) */
+"0000000000000040" /* scaleY (float64 2) */
+"0000000000000840" /* ipX (float64 3) */
+"0000000000001040" /* ipY (float64 4) */
+"0000000000001440" /* skewX (float64 5) */
+"0000000000001840" /* skewY (float64 6) */
+"0A000000"         /* SRID (int32 10) */
+"0100"             /* width (uint16 1) */
+"0100"             /* height (uint16 1) */
+"40"               /* First band type (1BB, in memory, hasnodata) */
+"00"               /* nodata value (0) */
+"01"               /* pix(0,0) == 1 */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 1);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 1);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 1);
+       {
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_1BB);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian...
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       rt_raster_destroy(raster);
+       free((/*no const*/ void*)out);
+
+       /* ------------------------------------------------------ */
+       /* 3x2, big endian, band0(8BSI)                           */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"01"               /* little endian (uint8 ndr) */
+"0000"             /* version (uint16 0) */
+"0100"             /* nBands (uint16 1) */
+"000000000000F03F" /* scaleX (float64 1) */
+"0000000000000040" /* scaleY (float64 2) */
+"0000000000000840" /* ipX (float64 3) */
+"0000000000001040" /* ipY (float64 4) */
+"0000000000001440" /* skewX (float64 5) */
+"0000000000001840" /* skewY (float64 6) */
+"0A000000"         /* SRID (int32 10) */
+"0300"             /* width (uint16 3) */
+"0200"             /* height (uint16 2) */
+"43"               /* First band type (8BSI, in memory, hasnodata) */
+"FF"               /* nodata value (-1) */
+"FF"               /* pix(0,0) == -1 */
+"00"               /* pix(1,0) ==  0 */
+"01"               /* pix(2,0) == 1 */
+"7F"               /* pix(0,1) == 127 */
+"0A"               /* pix(1,1) == 10 */
+"02"               /* pix(2,1) == 2 */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 1);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 3);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 2);
+       {
+               double val;
+               int failure;
+
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_8BSI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, -1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, -1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 127, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 10, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian...
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       free((/*no const*/ void*)out);
+
+       {
+               void *serialized;
+               rt_raster rast2;
+
+               serialized = rt_raster_serialize(raster);
+               rast2 = rt_raster_deserialize(serialized, FALSE);
+
+               rt_raster_destroy(rast2);
+               free(serialized);
+
+       }
+
+       rt_raster_destroy(raster);
+
+       /* ------------------------------------------------------ */
+       /* 3x2, little endian, band0(16BSI)                       */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"01"               /* little endian (uint8 ndr) */
+"0000"             /* version (uint16 0) */
+"0100"             /* nBands (uint16 1) */
+"000000000000F03F" /* scaleX (float64 1) */
+"0000000000000040" /* scaleY (float64 2) */
+"0000000000000840" /* ipX (float64 3) */
+"0000000000001040" /* ipY (float64 4) */
+"0000000000001440" /* skewX (float64 5) */
+"0000000000001840" /* skewY (float64 6) */
+"0A000000"         /* SRID (int32 10) */
+"0300"             /* width (uint16 3) */
+"0200"             /* height (uint16 2) */
+"05"               /* First band type (16BSI, in memory) */
+"FFFF"               /* nodata value (-1) */
+"FFFF"               /* pix(0,0) == -1 */
+"0000"               /* pix(1,0) ==  0 */
+"F0FF"               /* pix(2,0) == -16 */
+"7F00"               /* pix(0,1) == 127 */
+"0A00"               /* pix(1,1) == 10 */
+"0200"               /* pix(2,1) == 2 */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 1);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 3);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 2);
+       {
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_16BSI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(!rt_band_get_hasnodata_flag(band));
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, -1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, -16, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 127, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 10, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       rt_raster_destroy(raster);
+       free((/*no const*/ void*)out);
+
+       /* ------------------------------------------------------ */
+       /* 3x2, big endian, band0(16BSI)                          */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"00"               /* big endian (uint8 xdr) */
+"0000"             /* version (uint16 0) */
+"0001"             /* nBands (uint16 1) */
+"3FF0000000000000" /* scaleX (float64 1) */
+"4000000000000000" /* scaleY (float64 2) */
+"4008000000000000" /* ipX (float64 3) */
+"4010000000000000" /* ipY (float64 4) */
+"4014000000000000" /* skewX (float64 5) */
+"4018000000000000" /* skewY (float64 6) */
+"0000000A"         /* SRID (int32 10) */
+"0003"             /* width (uint16 3) */
+"0002"             /* height (uint16 2) */
+"05"               /* First band type (16BSI, in memory) */
+"FFFF"             /* nodata value (-1) */
+"FFFF"             /* pix(0,0) == -1 */
+"0000"             /* pix(1,0) ==  0 */
+"FFF0"             /* pix(2,0) == -16 */
+"007F"             /* pix(0,1) == 127 */
+"000A"             /* pix(1,1) == 10 */
+"0002"             /* pix(2,1) == 2 */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 1);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 3);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 2);
+       {
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_16BSI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(!rt_band_get_hasnodata_flag(band));
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, -1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, -16, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 127, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 10, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 1, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       rt_raster_destroy(raster);
+       free((/*no const*/ void*)out);
+
+       /* ------------------------------------------------------ */
+       /* 3x2, bit endian, band0(16BSI ext: 3;/tmp/t.tif)        */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"00"               /* big endian (uint8 xdr) */
+"0000"             /* version (uint16 0) */
+"0001"             /* nBands (uint16 1) */
+"3FF0000000000000" /* scaleX (float64 1) */
+"4000000000000000" /* scaleY (float64 2) */
+"4008000000000000" /* ipX (float64 3) */
+"4010000000000000" /* ipY (float64 4) */
+"4014000000000000" /* skewX (float64 5) */
+"4018000000000000" /* skewY (float64 6) */
+"0000000A"         /* SRID (int32 10) */
+"0003"             /* width (uint16 3) */
+"0002"             /* height (uint16 2) */
+"C5"               /* First band type (16BSI, on disk, hasnodata) */
+"FFFF"             /* nodata value (-1) */
+"03"               /* ext band num == 3 */
+/* ext band path == /tmp/t.tif */
+"2F746D702F742E74696600"
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 1);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 1, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), 2, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 4, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 5, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 6, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 10);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 3);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 2);
+       {
+               double val;
+               uint8_t bandnum = 0;
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_16BSI);
+               CU_ASSERT(rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, -1, DBL_EPSILON);
+               CU_ASSERT_STRING_EQUAL(rt_band_get_ext_path(band), "/tmp/t.tif");
+               CU_ASSERT_EQUAL(rt_band_get_ext_band_num(band, &bandnum), ES_NONE);
+               CU_ASSERT_EQUAL(bandnum, 3);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       rt_raster_destroy(raster);
+       free((/*no const*/ void*)out);
+
+       /* ------------------------------------------------------ */
+       /* 1x3, little endian, band0 16BSI, nodata 1, srid -1     */
+       /* ------------------------------------------------------ */
+
+       hexwkb =
+"01"               /* little endian (uint8 ndr) */
+"0000"             /* version (uint16 0) */
+"0100"             /* nBands (uint16 1) */
+"0000000000805640" /* scaleX (float64 90.0) */
+"00000000008056C0" /* scaleY (float64 -90.0) */
+"000000001C992D41" /* ipX (float64 969870.0) */
+"00000000E49E2341" /* ipY (float64 642930.0) */
+"0000000000000000" /* skewX (float64 0) */
+"0000000000000000" /* skewY (float64 0) */
+"FFFFFFFF"         /* SRID (int32 -1) */
+"0300"             /* width (uint16 3) */
+"0100"             /* height (uint16 1) */
+"45"               /* First band type (16BSI, in memory, hasnodata) */
+"0100"             /* nodata value (1) */
+"0100"             /* pix(0,0) == 1 */
+"B401"             /* pix(1,0) == 436 */
+"AF01"             /* pix(2,0) == 431 */
+       ;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 1);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 90, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), -90, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 969870.0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 642930.0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 0);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 3);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 1);
+       {
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_16BSI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 436, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 431, DBL_EPSILON);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %d\n", strlen(hexwkb));
+       printf("out hexwkb len: %d\n", len);
+       printf(" in hexwkb: %s\n", hexwkb);
+       printf("out hexwkb: %s\n", out);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+       free((/*no const*/ void*)out);
+
+       {
+               void *serialized;
+               rt_raster rast2;
+
+               serialized = rt_raster_serialize(raster);
+               rast2 = rt_raster_deserialize(serialized, FALSE);
+
+               rt_raster_destroy(rast2);
+               free(serialized);
+       }
+
+       rt_raster_destroy(raster);
+
+       /* ------------------------------------------------------ */
+       /* 5x5, little endian, 3 x band 8BUI (RGB),               */
+       /* nodata 0, srid -1                                      */
+       /* Test case completes regress/bug_test_car5.sql          */
+       /* Test case repeated 4 times to mimic 4 tiles insertion  */
+       /* ------------------------------------------------------ */
+       for (i = 0; i < 5; ++i)
+       {
+
+       hexwkb =
+"01"                 /* little endian (uint8 ndr) */
+"0000"              /* version (uint16 0) */
+"0300"              /* nBands (uint16 3) */
+"9A9999999999A93F"  /* scaleX (float64 0.050000) */
+"9A9999999999A9BF"  /* scaleY (float64 -0.050000) */
+"000000E02B274A41"  /* ipX (float64 3427927.750000) */
+"0000000077195641"  /* ipY (float64 5793244.000000) */
+"0000000000000000"  /* skewX (float64 0.000000) */
+"0000000000000000"  /* skewY (float64 0.000000) */
+"FFFFFFFF"          /* srid (int32 -1) */
+"0500"              /* width (uint16 5) */
+"0500"              /* height (uint16 5) */
+"44"                /* 1st band pixel type (8BUI, in memory, hasnodata) */
+"00"                /* 1st band nodata 0 */
+"FDFEFDFEFEFDFEFEFDF9FAFEFEFCF9FBFDFEFEFDFCFAFEFEFE" /* 1st band pixels */
+"44"                /* 2nd band pixel type (8BUI, in memory, hasnodata) */
+"00"                /* 2nd band nodata 0 */
+"4E627AADD16076B4F9FE6370A9F5FE59637AB0E54F58617087" /* 2nd band pixels */
+"44"                /* 3rd band pixel type (8BUI, in memory, hasnodata) */
+"00"                /* 3rd band nodata 0 */
+"46566487A1506CA2E3FA5A6CAFFBFE4D566DA4CB3E454C5665" /* 3rd band pixels */
+;
+
+       raster = rt_raster_from_hexwkb(hexwkb, strlen(hexwkb));
+       CU_ASSERT(raster != NULL);
+       CU_ASSERT_EQUAL(rt_raster_get_num_bands(raster), 3);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_scale(raster), 0.05, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_scale(raster), -0.05, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_offset(raster), 3427927.75, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_offset(raster), 5793244.00, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_x_skew(raster), 0.0, DBL_EPSILON);
+       CU_ASSERT_DOUBLE_EQUAL(rt_raster_get_y_skew(raster), 0.0, DBL_EPSILON);
+       CU_ASSERT_EQUAL(rt_raster_get_srid(raster), 0);
+       CU_ASSERT_EQUAL(rt_raster_get_width(raster), 5);
+       CU_ASSERT_EQUAL(rt_raster_get_height(raster), 5);
+       {
+               /* Test 1st band */
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 0);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_8BUI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 253, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 254, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 253, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 3, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 254, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 4, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 254, DBL_EPSILON);
+       }
+
+       {
+               /* Test 2nd band */
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 1);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_8BUI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 78, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 98, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 122, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 3, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 173, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 4, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 209, DBL_EPSILON);
+       }
+
+       {
+               /* Test 3rd band */
+               double val;
+               int failure;
+               rt_band band = rt_raster_get_band(raster, 2);
+               CU_ASSERT(band != NULL);
+               CU_ASSERT_EQUAL(rt_band_get_pixtype(band), PT_8BUI);
+               CU_ASSERT(!rt_band_is_offline(band));
+               CU_ASSERT(rt_band_get_hasnodata_flag(band));
+               rt_band_get_nodata(band, &val);
+               CU_ASSERT_DOUBLE_EQUAL(val, 0, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 0, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 70, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 1, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 86, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 2, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 100, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 3, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 135, DBL_EPSILON);
+
+               failure = rt_band_get_pixel(band, 4, 0, &val, NULL);
+               CU_ASSERT_EQUAL(failure, ES_NONE);
+               CU_ASSERT_DOUBLE_EQUAL(val, 161, DBL_EPSILON);
+       }
+
+       out  = rt_raster_to_hexwkb(raster, &len);
+/*
+       printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb));
+       printf("out hexwkb len: %u\n", len);
+*/
+       CU_ASSERT_EQUAL(len, strlen(hexwkb));
+/* would depend on machine endian
+       CU_ASSERT_STRING_EQUAL(hexwkb, out);
+*/
+
+       free((/*no const*/ void*)out);
+       {
+               void *serialized;
+               rt_raster rast2;
+
+               serialized = rt_raster_serialize(raster);
+               rast2 = rt_raster_deserialize(serialized, FALSE);
+
+               rt_raster_destroy(rast2);
+               free(serialized);
+       }
+       rt_raster_destroy(raster);
+
+       } /* for-loop running car5 tests */
+
+       /* ------------------------------------------------------ */
+       /* TODO: New test cases                                   */
+       /* ------------------------------------------------------ */
+
+       /* new test case */
+
+       /* ------------------------------------------------------ */
+       /*  Success summary                                       */
+       /* ------------------------------------------------------ */
+
+/*
+       printf("All tests successful !\n");
+*/
+}
+
+/* register tests */
+CU_TestInfo raster_wkb_tests[] = {
+       PG_TEST(test_raster_wkb),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo raster_wkb_suite = {"raster_wkb",  NULL,  NULL, raster_wkb_tests};
diff --git a/raster/test/cunit/cu_spatial_relationship.c b/raster/test/cunit/cu_spatial_relationship.c
new file mode 100644 (file)
index 0000000..6090495
--- /dev/null
@@ -0,0 +1,4795 @@
+/*
+ * PostGIS Raster - Raster Types for PostGIS
+ * http://www.postgis.org/support/wiki/index.php?WKTRasterHomePage
+ *
+ * Copyright (C) 2012 Regents of the University of California
+ *   <bkpark@ucdavis.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+static void test_raster_geos_overlaps() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       rtn = rt_raster_overlaps(
+               rast1, -1,
+               rast2, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_overlaps(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_geos_touches() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_touches(
+               rast1, -1,
+               rast2, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 3)
+       */
+       rt_raster_set_offsets(rast2, 0, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-1, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 3)
+       */
+       rt_raster_set_offsets(rast2, -1, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_touches(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_geos_contains() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_contains(
+               rast1, -1,
+               rast2, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 3)
+       */
+       rt_raster_set_offsets(rast2, 0, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-1, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 3)
+       */
+       rt_raster_set_offsets(rast2, -1, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_contains(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_geos_contains_properly() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_contains_properly(
+               rast1, -1,
+               rast2, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 3)
+       */
+       rt_raster_set_offsets(rast2, 0, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-1, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 3)
+       */
+       rt_raster_set_offsets(rast2, -1, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_contains_properly(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_geos_covers() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_covers(
+               rast1, -1,
+               rast2, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 3)
+       */
+       rt_raster_set_offsets(rast2, 0, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-1, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 3)
+       */
+       rt_raster_set_offsets(rast2, -1, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_covers(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_geos_covered_by() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_coveredby(
+               rast1, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_coveredby(
+               rast2, -1,
+               rast1, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 3)
+       */
+       rt_raster_set_offsets(rast2, 0, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-1, 1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 3)
+       */
+       rt_raster_set_offsets(rast2, -1, 1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_coveredby(
+               rast2, 0,
+               rast1, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_within_distance() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast1, 0,
+               0.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast1, 0,
+               -1.,
+               &result
+       );
+       CU_ASSERT_NOT_EQUAL(rtn, ES_NONE);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               1.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       rtn = rt_raster_within_distance(
+               rast1, -1,
+               rast2, -1,
+               2.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               1.1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-10, -1)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (-7, 2)
+       */
+       rt_raster_set_offsets(rast2, -10, -1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               5,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               6,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_fully_within_distance() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast1, 0,
+               0.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast1, 0,
+               -1.,
+               &result
+       );
+       CU_ASSERT_NOT_EQUAL(rtn, ES_NONE);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               1.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, -1,
+               rast2, -1,
+               5.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               2.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               5.,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               5,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               10,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               5.9,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               3,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               2,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               6,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               4.25,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               3.5,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               3.65,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               3.6,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-10, -1)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (-7, 2)
+       */
+       rt_raster_set_offsets(rast2, -10, -1);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               5,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               11.5,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               6.1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               7.1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_fully_within_distance(
+               rast1, 0,
+               rast2, 0,
+               8,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_intersects() {
+       rt_raster rast1;
+       rt_raster rast2;
+       rt_band band1;
+       rt_band band2;
+       double nodata;
+       int rtn;
+       int result;
+
+       /*
+               rast1
+
+               (-1, -1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (1, 1)
+       */
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+       rt_raster_set_offsets(rast1, -1, -1);
+
+       band1 = cu_add_band(rast1, PT_8BUI, 1, 0);
+       CU_ASSERT(band1 != NULL);
+       rt_band_set_nodata(band1, 0, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band1, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band1, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rast2 = rt_raster_new(2, 2);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       rtn = rt_raster_intersects(
+               rast1, -1,
+               rast2, -1,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |1|0|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|1|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                               |0|0|
+                                               +-+-+
+                                                               (2, 2)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (2, 0)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (4, 2)
+       */
+       rt_raster_set_offsets(rast2, 2, 0);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rt_raster_set_scale(rast2, 0.4, 0.4);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-0.1, 0.1)
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                               |1|1|
+                                               +-+-+
+                                                               (0.9, 0.9)
+       */
+       rt_raster_set_offsets(rast2, -0.1, 0.1);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /*
+               rast2
+
+               (0, 0)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (3, 3)
+       */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rt_band_get_nodata(band2, &nodata);
+       CU_ASSERT_EQUAL(nodata, 0);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                               |1|1|1|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rt_raster_set_offsets(rast2, -2, -2);
+
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 1, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|1|
+                                               +-+-+-+
+                                               |1|1|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|1|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /*
+               rast2
+
+               (-2, -2)
+                                               +-+-+-+
+                                               |0|1|0|
+                                               +-+-+-+
+                                               |1|0|0|
+                                               +-+-+-+
+                                               |0|0|0|
+                                               +-+-+-+
+                                                                       (1, 1)
+       */
+       rtn = rt_band_set_pixel(band2, 0, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 0, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+
+       /* skew tests */
+       /* rast2 (skewed by -0.5, 0.5) */
+       rast2 = rt_raster_new(3, 3);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+
+       band2 = cu_add_band(rast2, PT_8BUI, 1, 0);
+       CU_ASSERT(band2 != NULL);
+       rt_band_set_nodata(band2, 0, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 0, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 1, 2, 3, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 0, 1, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 1, 2, NULL);
+       rtn = rt_band_set_pixel(band2, 2, 2, 3, NULL);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by -1, 1) */
+       rt_raster_set_skews(rast2, -1, 1);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       /* rast2 (skewed by 1, -1) */
+       rt_raster_set_skews(rast2, 1, -1);
+
+       rtn = rt_raster_intersects(
+               rast1, 0,
+               rast2, 0,
+               &result
+       );
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(result, 1);
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+static void test_raster_same_alignment() {
+       rt_raster rast1;
+       rt_raster rast2;
+       int rtn;
+       int aligned;
+       char *reason;
+
+       rast1 = rt_raster_new(2, 2);
+       CU_ASSERT(rast1 != NULL);
+       rt_raster_set_scale(rast1, 1, 1);
+
+       rast2 = rt_raster_new(10, 10);
+       CU_ASSERT(rast2 != NULL);
+       rt_raster_set_scale(rast2, 1, 1);
+
+       rtn = rt_raster_same_alignment(rast1, rast2, &aligned, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(aligned, 0);
+
+       rt_raster_set_scale(rast2, 0.1, 0.1);
+       rtn = rt_raster_same_alignment(rast1, rast2, &aligned, &reason);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(aligned, 0);
+       CU_ASSERT_STRING_EQUAL(reason, "The rasters have different scales on the X axis");
+       rt_raster_set_scale(rast2, 1, 1);
+
+       rt_raster_set_skews(rast2, -0.5, 0.5);
+       rtn = rt_raster_same_alignment(rast1, rast2, &aligned, &reason);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(aligned, 0);
+       CU_ASSERT_STRING_EQUAL(reason, "The rasters have different skews on the X axis");
+       rt_raster_set_skews(rast2, 0, 0);
+
+       rt_raster_set_offsets(rast2, 1, 1);
+       rtn = rt_raster_same_alignment(rast1, rast2, &aligned, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(aligned, 0);
+
+       rt_raster_set_offsets(rast2, 2, 3);
+       rtn = rt_raster_same_alignment(rast1, rast2, &aligned, NULL);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_NOT_EQUAL(aligned, 0);
+
+       rt_raster_set_offsets(rast2, 0.1, 0.1);
+       rtn = rt_raster_same_alignment(rast1, rast2, &aligned, &reason);
+       CU_ASSERT_EQUAL(rtn, ES_NONE);
+       CU_ASSERT_EQUAL(aligned, 0);
+       CU_ASSERT_STRING_EQUAL(reason, "The rasters (pixel corner coordinates) are not aligned");
+
+       cu_free_raster(rast2);
+       cu_free_raster(rast1);
+}
+
+/* register tests */
+CU_TestInfo spatial_relationship_tests[] = {
+       PG_TEST(test_raster_geos_overlaps),
+       PG_TEST(test_raster_geos_touches),
+       PG_TEST(test_raster_geos_contains),
+       PG_TEST(test_raster_geos_contains_properly),
+       PG_TEST(test_raster_geos_covers),
+       PG_TEST(test_raster_geos_covered_by),
+       PG_TEST(test_raster_within_distance),
+       PG_TEST(test_raster_fully_within_distance),
+       PG_TEST(test_raster_intersects),
+       PG_TEST(test_raster_same_alignment),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo spatial_relationship_suite = {"spatial_relationship",  NULL,  NULL, spatial_relationship_tests};
diff --git a/raster/test/cunit/cu_tester.c b/raster/test/cunit/cu_tester.c
new file mode 100644 (file)
index 0000000..44e88a9
--- /dev/null
@@ -0,0 +1,260 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2008 Paul Ramsey <pramsey@cleverelephant.ca>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "CUnit/Basic.h"
+#include "cu_tester.h"
+
+/* ADD YOUR SUITE HERE (1 of 2) */
+extern CU_SuiteInfo pixtype_suite;
+extern CU_SuiteInfo raster_basics_suite;
+extern CU_SuiteInfo band_basics_suite;
+extern CU_SuiteInfo raster_wkb_suite;
+extern CU_SuiteInfo gdal_suite;
+extern CU_SuiteInfo raster_geometry_suite;
+extern CU_SuiteInfo raster_misc_suite;
+extern CU_SuiteInfo band_stats_suite;
+extern CU_SuiteInfo band_misc_suite;
+extern CU_SuiteInfo mapalgebra_suite;
+extern CU_SuiteInfo spatial_relationship_suite;
+
+/*
+** The main() function for setting up and running the tests.
+** Returns a CUE_SUCCESS on successful running, another
+** CUnit error code on failure.
+*/
+int main(int argc, char *argv[])
+{
+       /* ADD YOUR SUITE HERE (2 of 2) */
+       CU_SuiteInfo suites[] =
+       {
+               pixtype_suite,
+               raster_basics_suite,
+               band_basics_suite,
+               raster_wkb_suite,
+               gdal_suite,
+               raster_geometry_suite,
+               raster_misc_suite,
+               band_stats_suite,
+               band_misc_suite,
+               spatial_relationship_suite,
+               mapalgebra_suite,
+               CU_SUITE_INFO_NULL
+       };
+
+       int index;
+       char *suite_name;
+       CU_pSuite suite_to_run;
+       char *test_name;
+       CU_pTest test_to_run;
+       CU_ErrorCode errCode = 0;
+       CU_pTestRegistry registry;
+       int num_run;
+       int num_failed;
+
+       /* initialize the CUnit test registry */
+       if (CUE_SUCCESS != CU_initialize_registry())
+       {
+               errCode = CU_get_error();
+               printf("    Error attempting to initialize registry: %d.  See CUError.h for error code list.\n", errCode);
+               return errCode;
+       }
+
+       /* Register all the test suites. */
+       if (CUE_SUCCESS != CU_register_suites(suites))
+       {
+               errCode = CU_get_error();
+               printf("    Error attempting to register test suites: %d.  See CUError.h for error code list.\n", errCode);
+               return errCode;
+       }
+
+       /* Run all tests using the CUnit Basic interface */
+       CU_basic_set_mode(CU_BRM_VERBOSE);
+       if (argc <= 1)
+       {
+               errCode = CU_basic_run_tests();
+       }
+       else
+       {
+               /* NOTE: The cunit functions used here (CU_get_registry, CU_get_suite_by_name, and CU_get_test_by_name) are
+                *       listed with the following warning: "Internal CUnit system functions.  Should not be routinely called by users."
+                *       However, there didn't seem to be any other way to get tests by name, so we're calling them. */
+               registry = CU_get_registry();
+               for (index = 1; index < argc; index++)
+               {
+                       suite_name = argv[index];
+                       test_name = NULL;
+                       suite_to_run = CU_get_suite_by_name(suite_name, registry);
+                       if (NULL == suite_to_run)
+                       {
+                               /* See if it's a test name instead of a suite name. */
+                               suite_to_run = registry->pSuite;
+                               while (suite_to_run != NULL)
+                               {
+                                       test_to_run = CU_get_test_by_name(suite_name, suite_to_run);
+                                       if (test_to_run != NULL)
+                                       {
+                                               /* It was a test name. */
+                                               test_name = suite_name;
+                                               suite_name = suite_to_run->pName;
+                                               break;
+                                       }
+                                       suite_to_run = suite_to_run->pNext;
+                               }
+                       }
+                       if (suite_to_run == NULL)
+                       {
+                               printf("\n'%s' does not appear to be either a suite name or a test name.\n\n", suite_name);
+                       }
+                       else
+                       {
+                               if (test_name != NULL)
+                               {
+                                       /* Run only this test. */
+                                       printf("\nRunning test '%s' in suite '%s'.\n", test_name, suite_name);
+                                       /* This should be CU_basic_run_test, but that method is broken, see:
+                                        *     https://sourceforge.net/tracker/?func=detail&aid=2851925&group_id=32992&atid=407088
+                                        * This one doesn't output anything for success, so we have to do it manually. */
+                                       errCode = CU_run_test(suite_to_run, test_to_run);
+                                       if (errCode != CUE_SUCCESS)
+                                       {
+                                               printf("    Error attempting to run tests: %d.  See CUError.h for error code list.\n", errCode);
+                                       }
+                                       else
+                                       {
+                                               num_run = CU_get_number_of_asserts();
+                                               num_failed = CU_get_number_of_failures();
+                                               printf("\n    %s - asserts - %3d passed, %3d failed, %3d total.\n\n",
+                                                      (0 == num_failed ? "PASSED" : "FAILED"), (num_run - num_failed), num_failed, num_run);
+                                       }
+                               }
+                               else
+                               {
+                                       /* Run all the tests in the suite. */
+                                       printf("\nRunning all tests in suite '%s'.\n", suite_name);
+                                       /* This should be CU_basic_run_suite, but that method is broken, see:
+                                        *     https://sourceforge.net/tracker/?func=detail&aid=2851925&group_id=32992&atid=407088
+                                        * This one doesn't output anything for success, so we have to do it manually. */
+                                       errCode = CU_run_suite(suite_to_run);
+                                       if (errCode != CUE_SUCCESS)
+                                       {
+                                               printf("    Error attempting to run tests: %d.  See CUError.h for error code list.\n", errCode);
+                                       }
+                                       else
+                                       {
+                                               num_run = CU_get_number_of_tests_run();
+                                               num_failed = CU_get_number_of_tests_failed();
+                                               printf("\n    %s -   tests - %3d passed, %3d failed, %3d total.\n",
+                                                      (0 == num_failed ? "PASSED" : "FAILED"), (num_run - num_failed), num_failed, num_run);
+                                               num_run = CU_get_number_of_asserts();
+                                               num_failed = CU_get_number_of_failures();
+                                               printf("           - asserts - %3d passed, %3d failed, %3d total.\n\n",
+                                                      (num_run - num_failed), num_failed, num_run);
+                                       }
+                               }
+                       }
+               }
+               /* Presumably if the CU_basic_run_[test|suite] functions worked, we wouldn't have to do this. */
+               CU_basic_show_failures(CU_get_failure_list());
+               printf("\n\n"); /* basic_show_failures leaves off line breaks. */
+       }
+       num_failed = CU_get_number_of_failures();
+       CU_cleanup_registry();
+       return num_failed;
+}
+
+/**
+ * CUnit error handler
+ * Log message in a global var instead of printing in stderr
+ *
+ * CAUTION: Not stop execution on rterror case !!!
+ */
+static void cu_error_reporter(const char *fmt, va_list ap) {
+       char *msg;
+
+       /** This is a GNU extension.
+       * Dunno how to handle errors here.
+        */
+       if (!lw_vasprintf (&msg, fmt, ap)) {
+               va_end (ap);
+               return;
+       }
+
+       strncpy(cu_error_msg, msg, MAX_CUNIT_MSG_LENGTH);
+       rtdealloc(msg);
+}
+
+void cu_error_msg_reset() {
+       memset(cu_error_msg, '\0', MAX_CUNIT_MSG_LENGTH);
+}
+
+void cu_free_raster(rt_raster raster) {
+       uint16_t i;
+       uint16_t nbands = rt_raster_get_num_bands(raster);
+
+       for (i = 0; i < nbands; ++i) {
+               rt_band band = rt_raster_get_band(raster, i);
+               if (!rt_band_is_offline(band) && !rt_band_get_ownsdata_flag(band)) {
+                       void* mem = rt_band_get_data(band);
+                       if (mem) rtdealloc(mem);
+               }
+               rt_band_destroy(band);
+       }
+
+       rt_raster_destroy(raster);
+       raster = NULL;
+}
+
+rt_band cu_add_band(rt_raster raster, rt_pixtype pixtype, int hasnodata, double nodataval) {
+       void* mem = NULL;
+       int32_t bandNum = 0;
+       size_t datasize = 0;
+       rt_band band = NULL;
+       uint16_t width = 0;
+       uint16_t height = 0;
+
+       width = rt_raster_get_width(raster);
+       height = rt_raster_get_height(raster);
+
+       datasize = rt_pixtype_size(pixtype) * width * height;
+       mem = rtalloc(datasize);
+       CU_ASSERT(mem != NULL);
+
+       band = rt_band_new_inline(width, height, pixtype, hasnodata, nodataval, mem);
+       CU_ASSERT(band != NULL);
+       rt_band_set_ownsdata_flag(band, 1);
+
+       bandNum = rt_raster_add_band(raster, band, rt_raster_get_num_bands(raster));
+       CU_ASSERT(bandNum >= 0);
+
+       return band;
+}
+
+void lwgeom_init_allocators(void) {
+       lwalloc_var = default_allocator;
+       lwrealloc_var = default_reallocator;
+       lwfree_var = default_freeor;
+       lwnotice_var = default_noticereporter;
+       lwerror_var = cu_error_reporter;
+}
+
+void rt_init_allocators(void) {
+       rt_set_handlers(
+               default_rt_allocator,
+               default_rt_reallocator,
+               default_rt_deallocator,
+               cu_error_reporter,
+               default_rt_info_handler,
+               default_rt_warning_handler
+       );
+}
diff --git a/raster/test/cunit/cu_tester.h b/raster/test/cunit/cu_tester.h
new file mode 100644 (file)
index 0000000..26d5724
--- /dev/null
@@ -0,0 +1,31 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "rt_api.h"
+
+#define PG_TEST(test_func) { #test_func, test_func }
+#define MAX_CUNIT_MSG_LENGTH 512
+
+/* Contains the most recent error message generated by rterror. */
+char cu_error_msg[MAX_CUNIT_MSG_LENGTH+1];
+
+/* Resets cu_error_msg back to blank. */
+void cu_error_msg_reset(void);
+
+/* free raster object */
+void cu_free_raster(rt_raster raster);
+
+/* helper to add bands to raster */
+rt_band cu_add_band(
+       rt_raster raster,
+       rt_pixtype pixtype,
+       int hasnodata, double nodataval
+);