PostGIS  3.4.0dev-r@@SVN_REVISION@@
rt_pixel.c
Go to the documentation of this file.
1 /*
2  *
3  * WKTRaster - Raster Types for PostGIS
4  * http://trac.osgeo.org/postgis/wiki/WKTRaster
5  *
6  * Copyright (C) 2011-2013 Regents of the University of California
7  * <bkpark@ucdavis.edu>
8  * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9  * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10  * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11  * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12  * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13  * Copyright (C) 2013 Nathaniel Hunter Clay <clay.nathaniel@gmail.com>
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software Foundation,
27  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28  *
29  */
30 
31 #include "librtcore.h"
32 #include "librtcore_internal.h"
33 
34 /******************************************************************************
35 * rt_pixeltype
36 ******************************************************************************/
37 
38 int
40  int pixbytes = -1;
41 
42  switch (pixtype) {
43  case PT_1BB:
44  case PT_2BUI:
45  case PT_4BUI:
46  case PT_8BSI:
47  case PT_8BUI:
48  pixbytes = 1;
49  break;
50  case PT_16BSI:
51  case PT_16BUI:
52  pixbytes = 2;
53  break;
54  case PT_32BSI:
55  case PT_32BUI:
56  case PT_32BF:
57  pixbytes = 4;
58  break;
59  case PT_64BF:
60  pixbytes = 8;
61  break;
62  default:
63  rterror("rt_pixtype_size: Unknown pixeltype %d", pixtype);
64  pixbytes = -1;
65  break;
66  }
67 
68  RASTER_DEBUGF(3, "Pixel type = %s and size = %d bytes",
69  rt_pixtype_name(pixtype), pixbytes);
70 
71  return pixbytes;
72 }
73 
74 int
76  return rt_pixtype_size(pixtype);
77 }
78 
80 rt_pixtype_index_from_name(const char* pixname) {
81  assert(pixname);
82 
83  if (strcmp(pixname, "1BB") == 0)
84  return PT_1BB;
85  else if (strcmp(pixname, "2BUI") == 0)
86  return PT_2BUI;
87  else if (strcmp(pixname, "4BUI") == 0)
88  return PT_4BUI;
89  else if (strcmp(pixname, "8BSI") == 0)
90  return PT_8BSI;
91  else if (strcmp(pixname, "8BUI") == 0)
92  return PT_8BUI;
93  else if (strcmp(pixname, "16BSI") == 0)
94  return PT_16BSI;
95  else if (strcmp(pixname, "16BUI") == 0)
96  return PT_16BUI;
97  else if (strcmp(pixname, "32BSI") == 0)
98  return PT_32BSI;
99  else if (strcmp(pixname, "32BUI") == 0)
100  return PT_32BUI;
101  else if (strcmp(pixname, "32BF") == 0)
102  return PT_32BF;
103  else if (strcmp(pixname, "64BF") == 0)
104  return PT_64BF;
105 
106  return PT_END;
107 }
108 
109 const char*
111 
112 
113  switch (pixtype) {
114  case PT_1BB:
115  return "1BB";
116  case PT_2BUI:
117  return "2BUI";
118  case PT_4BUI:
119  return "4BUI";
120  case PT_8BSI:
121  return "8BSI";
122  case PT_8BUI:
123  return "8BUI";
124  case PT_16BSI:
125  return "16BSI";
126  case PT_16BUI:
127  return "16BUI";
128  case PT_32BSI:
129  return "32BSI";
130  case PT_32BUI:
131  return "32BUI";
132  case PT_32BF:
133  return "32BF";
134  case PT_64BF:
135  return "64BF";
136  default:
137  rterror("rt_pixtype_name: Unknown pixeltype %d", pixtype);
138  return "Unknown";
139  }
140 }
141 
149 double
151  switch (pixtype) {
152  case PT_1BB: {
153  return (double) rt_util_clamp_to_1BB((double) CHAR_MIN);
154  }
155  case PT_2BUI: {
156  return 0;
157  }
158  case PT_4BUI: {
159  return 0;
160  }
161  case PT_8BUI: {
162  return 0;
163  }
164  case PT_8BSI: {
165  return (double) rt_util_clamp_to_8BSI((double) SCHAR_MIN);
166  }
167  case PT_16BSI: {
168  return (double) rt_util_clamp_to_16BSI((double) SHRT_MIN);
169  }
170  case PT_16BUI: {
171  return 0;
172  }
173  case PT_32BSI: {
174  return (double) rt_util_clamp_to_32BSI((double) INT_MIN);
175  }
176  case PT_32BUI: {
177  return 0;
178  }
179  case PT_32BF: {
180  return (double) -FLT_MAX;
181  }
182  case PT_64BF: {
183  return (double) -DBL_MAX;
184  }
185  default: {
186  rterror("rt_pixtype_get_min_value: Unknown pixeltype %d", pixtype);
187  return (double) rt_util_clamp_to_8BUI((double) CHAR_MIN);
188  }
189  }
190 }
191 
203  rt_pixtype pixtype,
204  double val, double refval,
205  int *isequal
206 ) {
207  assert(isequal != NULL);
208  *isequal = 0;
209 
210  switch (pixtype) {
211  case PT_1BB:
212  if (rt_util_clamp_to_1BB(val) == rt_util_clamp_to_1BB(refval))
213  *isequal = 1;
214  break;
215  case PT_2BUI:
216  if (rt_util_clamp_to_2BUI(val) == rt_util_clamp_to_2BUI(refval))
217  *isequal = 1;
218  break;
219  case PT_4BUI:
220  if (rt_util_clamp_to_4BUI(val) == rt_util_clamp_to_4BUI(refval))
221  *isequal = 1;
222  break;
223  case PT_8BSI:
224  if (rt_util_clamp_to_8BSI(val) == rt_util_clamp_to_8BSI(refval))
225  *isequal = 1;
226  break;
227  case PT_8BUI:
228  if (rt_util_clamp_to_8BUI(val) == rt_util_clamp_to_8BUI(refval))
229  *isequal = 1;
230  break;
231  case PT_16BSI:
233  *isequal = 1;
234  break;
235  case PT_16BUI:
237  *isequal = 1;
238  break;
239  case PT_32BSI:
241  *isequal = 1;
242  break;
243  case PT_32BUI:
245  *isequal = 1;
246  break;
247  case PT_32BF:
249  *isequal = 1;
250  break;
251  case PT_64BF:
252  if (FLT_EQ(val, refval))
253  *isequal = 1;
254  break;
255  default:
256  rterror("rt_pixtype_compare_clamped_values: Unknown pixeltype %d", pixtype);
257  return ES_ERROR;
258  }
259 
260  return ES_NONE;
261 }
262 
263 /******************************************************************************
264 * rt_pixel
265 ******************************************************************************/
266 
267 /*
268  * Convert an array of rt_pixel objects to two 2D arrays of value and NODATA.
269  * The dimensions of the returned 2D array are [Y][X], going by row Y and
270  * then column X.
271  *
272  * @param npixel : array of rt_pixel objects
273  * @param count : number of elements in npixel
274  * @param mask : mask to be respected when retruning array
275  * @param x : the column of the center pixel (0-based)
276  * @param y : the line of the center pixel (0-based)
277  * @param distancex : the number of pixels around the specified pixel
278  * along the X axis
279  * @param distancey : the number of pixels around the specified pixel
280  * along the Y axis
281  * @param value : pointer to pointer for 2D value array
282  * @param nodata : pointer to pointer for 2D NODATA array
283  * @param dimx : size of value and nodata along the X axis
284  * @param dimy : size of value and nodata along the Y axis
285  *
286  * @return ES_NONE on success, ES_ERROR on error
287  */
289  rt_pixel npixel, uint32_t count, rt_mask mask,
290  int x, int y,
291  uint16_t distancex, uint16_t distancey,
292  double ***value,
293  int ***nodata,
294  int *dimx, int *dimy
295 ) {
296  uint32_t i;
297  uint32_t j;
298  uint32_t dim[2] = {0};
299  double **values = NULL;
300  int **nodatas = NULL;
301  int zero[2] = {0};
302  int _x;
303  int _y;
304 
305  assert(npixel != NULL && count > 0);
306  assert(value != NULL);
307  assert(nodata != NULL);
308 
309  /* dimensions */
310  dim[0] = distancex * 2 + 1;
311  dim[1] = distancey * 2 + 1;
312  RASTER_DEBUGF(4, "dimensions = %d x %d", dim[0], dim[1]);
313 
314  /* make sure that the dimx and dimy match mask */
315  if (mask != NULL) {
316  if (dim[0] != mask->dimx || dim[1] != mask->dimy) {
317  rterror("rt_pixel_set_array: mask dimensions %d x %d do not match given dims %d x %d", mask->dimx, mask->dimy, dim[0], dim[1]);
318  return ES_ERROR;
319  }
320 
321  if (mask->values == NULL || mask->nodata == NULL) {
322  rterror("rt_pixel_set_array: Invalid mask");
323  return ES_ERROR;
324  }
325 
326  }
327 
328  /* establish 2D arrays (Y axis) */
329  values = rtalloc(sizeof(double *) * dim[1]);
330  nodatas = rtalloc(sizeof(int *) * dim[1]);
331 
332  if (values == NULL || nodatas == NULL) {
333  rterror("rt_pixel_set_to_array: Could not allocate memory for 2D array");
334  return ES_ERROR;
335  }
336 
337  /* initialize X axis */
338  for (i = 0; i < dim[1]; i++) {
339  values[i] = rtalloc(sizeof(double) * dim[0]);
340  nodatas[i] = rtalloc(sizeof(int) * dim[0]);
341 
342  if (values[i] == NULL || nodatas[i] == NULL) {
343  rterror("rt_pixel_set_to_array: Could not allocate memory for dimension of 2D array");
344 
345  if (values[i] == NULL) {
346  for (j = 0; j < i; j++) {
347  rtdealloc(values[j]);
348  rtdealloc(nodatas[j]);
349  }
350  }
351  else {
352  for (j = 0; j <= i; j++) {
353  rtdealloc(values[j]);
354  if (j < i)
355  rtdealloc(nodatas[j]);
356  }
357  }
358 
359  rtdealloc(values);
360  rtdealloc(nodatas);
361 
362  return ES_ERROR;
363  }
364 
365  /* set values to 0 */
366  memset(values[i], 0, sizeof(double) * dim[0]);
367 
368  /* set nodatas to 1 */
369  for (j = 0; j < dim[0]; j++)
370  nodatas[i][j] = 1;
371  }
372 
373  /* get 0,0 of grid */
374  zero[0] = x - distancex;
375  zero[1] = y - distancey;
376 
377  /* populate 2D arrays */
378  for (i = 0; i < count; i++) {
379  if (npixel[i].nodata)
380  continue;
381 
382  _x = npixel[i].x - zero[0];
383  _y = npixel[i].y - zero[1];
384 
385  RASTER_DEBUGF(4, "absolute x,y: %d x %d", npixel[i].x, npixel[i].y);
386  RASTER_DEBUGF(4, "relative x,y: %d x %d", _x, _y);
387 
388  /* no mask */
389  if (mask == NULL) {
390  values[_y][_x] = npixel[i].value;
391  nodatas[_y][_x] = 0;
392  }
393  /* mask */
394  else {
395  /* unweighted (boolean) mask */
396  if (mask->weighted == 0) {
397  /* pixel is set to zero or nodata */
398  if (FLT_EQ(mask->values[_y][_x], 0.0) || mask->nodata[_y][_x] == 1)
399  {
400  values[_y][_x] = 0;
401  nodatas[_y][_x] = 1;
402  }
403  /* use pixel */
404  else {
405  values[_y][_x] = npixel[i].value;
406  nodatas[_y][_x] = 0;
407  }
408  }
409  /* weighted mask */
410  else {
411  /* nodata */
412  if(mask->nodata[_y][_x] == 1) {
413  values[_y][_x] = 0;
414  nodatas[_y][_x] = 1;
415  }
416  /* apply weight to pixel value */
417  else {
418  values[_y][_x] = npixel[i].value * mask->values[_y][_x];
419  nodatas[_y][_x] = 0;
420  }
421  }
422  }
423 
424  RASTER_DEBUGF(4, "(x, y, nodata, value) = (%d, %d, %d, %f)", _x, _y, nodatas[_y][_x], values[_y][_x]);
425  }
426 
427  *value = &(*values);
428  *nodata = &(*nodatas);
429  if (dimx != NULL)
430  *dimx = dim[0];
431  if (dimy != NULL)
432  *dimy = dim[1];
433 
434  return ES_NONE;
435 }
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:219
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:191
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:306
int8_t rt_util_clamp_to_8BSI(double value)
Definition: rt_util.c:50
uint8_t rt_util_clamp_to_1BB(double value)
Definition: rt_util.c:35
int32_t rt_util_clamp_to_32BSI(double value)
Definition: rt_util.c:70
rt_pixtype
Definition: librtcore.h:187
@ PT_32BUI
Definition: librtcore.h:196
@ PT_2BUI
Definition: librtcore.h:189
@ PT_32BSI
Definition: librtcore.h:195
@ PT_END
Definition: librtcore.h:199
@ PT_4BUI
Definition: librtcore.h:190
@ PT_32BF
Definition: librtcore.h:197
@ PT_1BB
Definition: librtcore.h:188
@ PT_16BUI
Definition: librtcore.h:194
@ PT_8BSI
Definition: librtcore.h:191
@ PT_16BSI
Definition: librtcore.h:193
@ PT_64BF
Definition: librtcore.h:198
@ PT_8BUI
Definition: librtcore.h:192
#define FLT_EQ(x, y)
Definition: librtcore.h:2387
uint8_t rt_util_clamp_to_2BUI(double value)
Definition: rt_util.c:40
uint8_t rt_util_clamp_to_8BUI(double value)
Definition: rt_util.c:55
rt_errorstate
Enum definitions.
Definition: librtcore.h:181
@ ES_NONE
Definition: librtcore.h:182
@ ES_ERROR
Definition: librtcore.h:183
int16_t rt_util_clamp_to_16BSI(double value)
Definition: rt_util.c:60
uint8_t rt_util_clamp_to_4BUI(double value)
Definition: rt_util.c:45
void rtdealloc(void *mem)
Definition: rt_context.c:206
uint16_t rt_util_clamp_to_16BUI(double value)
Definition: rt_util.c:65
uint32_t rt_util_clamp_to_32BUI(double value)
Definition: rt_util.c:75
float rt_util_clamp_to_32F(double value)
Definition: rt_util.c:80
This library is the generic raster handling section of PostGIS.
int value
Definition: genraster.py:62
int count
Definition: genraster.py:57
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_pixel.c:80
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:150
int rt_pixtype_alignment(rt_pixtype pixtype)
Return alignment requirements for data in the given pixel type.
Definition: rt_pixel.c:75
rt_errorstate rt_pixtype_compare_clamped_values(rt_pixtype pixtype, double val, double refval, int *isequal)
Returns 1 if clamped values are equal, 0 if not equal, -1 if error.
Definition: rt_pixel.c:202
rt_errorstate rt_pixel_set_to_array(rt_pixel npixel, uint32_t count, rt_mask mask, int x, int y, uint16_t distancex, uint16_t distancey, double ***value, int ***nodata, int *dimx, int *dimy)
Definition: rt_pixel.c:288
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition: rt_pixel.c:39
double ** values
Definition: librtcore.h:2499
uint16_t dimy
Definition: librtcore.h:2498
uint16_t dimx
Definition: librtcore.h:2497
int ** nodata
Definition: librtcore.h:2500
int weighted
Definition: librtcore.h:2501
double value
Definition: librtcore.h:2491