]> granicus.if.org Git - postgis/commitdiff
Added rt_band_get_pixel_line() and regression tests
authorBborie Park <bkpark at ucdavis.edu>
Tue, 23 Oct 2012 22:44:28 +0000 (22:44 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Tue, 23 Oct 2012 22:44:28 +0000 (22:44 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10533 b70326c6-7e19-0410-871a-916f4a2858ee

raster/rt_core/rt_api.c
raster/rt_core/rt_api.h
raster/test/core/testapi.c

index 70e84e63225879b6188f57eed07812e32234f82d..2a7e04968c3be9bda2e09136fd8196c1edacf729 100644 (file)
@@ -2254,6 +2254,92 @@ rt_band_set_pixel(
        return rtn;
 }
 
+/**
+ * Get values of multiple pixels.  Unlike rt_band_get_pixel,
+ * values in vals are of the band's pixel type so cannot be
+ * assumed to be double.  Function uses memcpy.
+ *
+ * It is important to be careful when using this function as
+ * the number of values being fetched may exceed a pixel "row".
+ * Remember that the band values are stored in a stream (1-D array)
+ * regardless of what the raster's width and height might be.
+ * So, getting a number of values may cross multiple pixel "rows".
+ *
+ * @param band : the band to get pixel value from
+ * @param x : pixel column (0-based)
+ * @param y : pixel row (0-based)
+ * @param len : the number of pixels to get
+ * @param vals : the pixel values
+ * @param *nvals : the number of pixel values being returned
+ *
+ * @return values of multiple pixels
+ */
+int rt_band_get_pixel_line(
+       rt_band band,
+       int x, int y,
+       uint16_t len,
+       void **vals, uint16_t *nvals
+) {
+       uint8_t *_vals = NULL;
+       rt_pixtype pixtype = PT_END;
+       int pixsize = 0;
+       uint8_t *data = NULL;
+       uint32_t offset = 0; 
+       uint16_t _nvals = 0;
+       int maxlen = 0;
+       uint8_t *ptr = NULL;
+
+       assert(NULL != band);
+
+       if (
+               x < 0 || x >= band->width ||
+               y < 0 || y >= band->height
+       ) {
+               rtwarn("Attempting to get pixel values with out of range raster coordinates: (%d, %d)", x, y);
+               return -1;
+       }
+
+       data = rt_band_get_data(band);
+       if (data == NULL) {
+               rterror("rt_band_get_pixel_line: Cannot get band data");
+               return -1;
+       }
+
+       /* +1 for the nodata value */
+       offset = x + (y * band->width);
+       RASTER_DEBUGF(4, "offset = %d", offset);
+
+       pixtype = band->pixtype;
+       pixsize = rt_pixtype_size(band->pixtype);
+       RASTER_DEBUGF(4, "pixsize = %d", pixsize);
+
+       /* cap _nvals so that it doesn't overflow */
+       _nvals = len;
+       maxlen = band->width * band->height;
+
+       if ((maxlen - (int) (offset + _nvals)) < 0) {
+               _nvals = _nvals - (((int) (offset + _nvals)) - maxlen);
+               rtwarn("Limiting returning number values to %d", _nvals);
+       }
+       RASTER_DEBUGF(4, "_nvals = %d", _nvals);
+
+       ptr = data + (offset * pixsize);
+
+       _vals = rtalloc(_nvals * pixsize);
+       if (_vals == NULL) {
+               rterror("rt_band_get_pixel_line: Unable to allocate memory for pixel values");
+               return -1;
+       }
+
+       /* copy pixels */
+       memcpy(_vals, ptr, _nvals * pixsize);
+
+       *vals = _vals;
+       *nvals = _nvals;
+
+       return 0;
+}
+
 /**
  * Get pixel value. If band's isnodata flag is TRUE, value returned 
  * will be the band's NODATA value
index 47ac366404b387f660cbc20bdca0b98cedb9dfe0..88101f97ddd486abd2e91614e3b789477f22271c 100644 (file)
@@ -598,6 +598,33 @@ int rt_band_set_pixel(
        double val
 );
 
+/**
+ * Get values of multiple pixels.  Unlike rt_band_get_pixel,
+ * values in vals are of the band's pixel type so cannot be
+ * assumed to be double.  Function uses memcpy.
+ *
+ * It is important to be careful when using this function as
+ * the number of values being fetched may exceed a pixel "row".
+ * Remember that the band values are stored in a stream (1-D array)
+ * regardless of what the raster's width and height might be.
+ * So, getting a number of values may cross multiple pixel "rows".
+ *
+ * @param band : the band to get pixel value from
+ * @param x : pixel column (0-based)
+ * @param y : pixel row (0-based)
+ * @param len : the number of pixels to get
+ * @param vals : the pixel values
+ * @param *nvals : the number of pixel values being returned
+ *
+ * @return 0 if success, -1 otherwise
+ */
+int rt_band_get_pixel_line(
+       rt_band band,
+       int x, int y,
+       uint16_t len,
+       void **vals, uint16_t *nvals
+);
+
 /**
  * Get pixel value. If band's isnodata flag is TRUE, value returned 
  * will be the band's NODATA value
index 4c80c247014a007411be1ab65a197d8f9c433d97..8210b1da4bab5cdf767683545c8dcbca1abc7170 100644 (file)
@@ -8121,6 +8121,48 @@ static void testRasterClone() {
        deepRelease(rast1);
 }
 
+static void testGetPixelLine() {
+       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);
+       assert(rast);
+
+       rt_raster_set_scale(rast, 1, -1);
+
+       band = addBand(rast, PT_8BSI, 0, 0);
+       CHECK(band);
+
+       for (y = 0; y < maxY; y++) {
+               for (x = 0; x < maxX; x++)
+                       rt_band_set_pixel(band, x, y, x + (y * maxX));
+       }
+
+       err = rt_band_get_pixel_line(band, 0, 0, maxX, &vals, &nvals);
+       CHECK((err == 0));
+       CHECK((nvals == maxX));
+       CHECK((((int8_t *) vals)[3] == 3));
+       rtdealloc(vals);
+       
+       err = rt_band_get_pixel_line(band, 4, 4, maxX, &vals, &nvals);
+       CHECK((err == 0));
+       CHECK((nvals == 1));
+       CHECK((((int8_t *) vals)[0] == 24));
+       rtdealloc(vals);
+
+       err = rt_band_get_pixel_line(band, maxX, maxY, maxX, &vals, &nvals);
+       CHECK((err != 0));
+
+       deepRelease(rast);
+}
+
 int
 main()
 {
@@ -8443,6 +8485,10 @@ main()
                testRasterClone();
                printf("OK\n");
 
+               printf("Test rt_band_get_pixel_line... ");
+               testGetPixelLine();
+               printf("OK\n");
+
     deepRelease(raster);
 
     return EXIT_SUCCESS;