GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gis/get_row.c
Go to the documentation of this file.
1 
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 
20 #include <rpc/types.h> /* need this for sgi */
21 #include <rpc/xdr.h>
22 
23 #include <grass/config.h>
24 #include <grass/glocale.h>
25 
26 #include "G.h"
27 
28 /*--------------------------------------------------------------------------*/
29 
30 #define NULL_FILE "null"
31 
32 /*--------------------------------------------------------------------------*/
33 
34 static int embed_nulls(int, void *, int, RASTER_MAP_TYPE, int, int);
35 
36 /*--------------------------------------------------------------------------*/
37 
38 static int compute_window_row(int fd, int row, int *cellRow)
39 {
40  struct fileinfo *fcb = &G__.fileinfo[fd];
41  double f;
42  int r;
43 
44  /* check for row in window */
45  if (row < 0 || row >= G__.window.rows) {
46  G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"),
47  fcb->name, fcb->mapset, row);
48 
49  return -1;
50  }
51 
52  /* convert window row to cell file row */
53  f = row * fcb->C1 + fcb->C2;
54  r = (int)f;
55  if (f < r) /* adjust for rounding up of negatives */
56  r--;
57 
58  if (r < 0 || r >= fcb->cellhd.rows)
59  return 0;
60 
61  *cellRow = r;
62 
63  return 1;
64 }
65 
66 /*--------------------------------------------------------------------------*/
67 
68 static void do_reclass_int(int fd, void *cell, int null_is_zero)
69 {
70  struct fileinfo *fcb = &G__.fileinfo[fd];
71  CELL *c = cell;
72  CELL *reclass_table = fcb->reclass.table;
73  CELL min = fcb->reclass.min;
74  CELL max = fcb->reclass.max;
75  int i;
76 
77  for (i = 0; i < G__.window.cols; i++) {
78  if (G_is_c_null_value(&c[i])) {
79  if (null_is_zero)
80  c[i] = 0;
81  continue;
82  }
83 
84  if (c[i] < min || c[i] > max) {
85  if (null_is_zero)
86  c[i] = 0;
87  else
88  G_set_c_null_value(&c[i], 1);
89  continue;
90  }
91 
92  c[i] = reclass_table[c[i] - min];
93 
94  if (null_is_zero && G_is_c_null_value(&c[i]))
95  c[i] = 0;
96  }
97 }
98 
99 /*--------------------------------------------------------------------------*/
100 
101 static int read_data_fp_compressed(int fd, int row, unsigned char *data_buf,
102  int *nbytes)
103 {
104  struct fileinfo *fcb = &G__.fileinfo[fd];
105  off_t t1 = fcb->row_ptr[row];
106  off_t t2 = fcb->row_ptr[row + 1];
107  size_t readamount = t2 - t1;
108  size_t bufsize = fcb->cellhd.cols * fcb->nbytes;
109 
110  if (lseek(fd, t1, SEEK_SET) < 0)
111  return -1;
112 
113  *nbytes = fcb->nbytes;
114 
115  if ((size_t) G_zlib_read(fd, readamount, data_buf, bufsize) != bufsize)
116  return -1;
117 
118  return 0;
119 }
120 
121 /*--------------------------------------------------------------------------*/
122 
123 static void rle_decompress(unsigned char *dst, const unsigned char *src,
124  int nbytes, int size)
125 {
126  int pairs = size / (nbytes + 1);
127  int i;
128 
129  for (i = 0; i < pairs; i++) {
130  int repeat = *src++;
131  int j;
132 
133  for (j = 0; j < repeat; j++) {
134  memcpy(dst, src, nbytes);
135  dst += nbytes;
136  }
137 
138  src += nbytes;
139  }
140 }
141 
142 static int read_data_compressed(int fd, int row, unsigned char *data_buf,
143  int *nbytes)
144 {
145  struct fileinfo *fcb = &G__.fileinfo[fd];
146  off_t t1 = fcb->row_ptr[row];
147  off_t t2 = fcb->row_ptr[row + 1];
148  ssize_t readamount = t2 - t1;
149  unsigned char *cmp = G__.compressed_buf;
150  int n;
151 
152  if (lseek(fd, t1, SEEK_SET) < 0)
153  return -1;
154 
155  if (read(fd, cmp, readamount) != readamount)
156  return -1;
157 
158  /* Now decompress the row */
159  if (fcb->cellhd.compressed > 0) {
160  /* one byte is nbyte count */
161  n = *nbytes = *cmp++;
162  readamount--;
163  }
164  else
165  /* pre 3.0 compression */
166  n = *nbytes = fcb->nbytes;
167 
168  if (fcb->cellhd.compressed < 0 || readamount < n * fcb->cellhd.cols) {
169  if (fcb->cellhd.compressed == 2)
170  G_zlib_expand(cmp, readamount, data_buf, n * fcb->cellhd.cols);
171  else
172  rle_decompress(data_buf, cmp, n, readamount);
173  }
174  else
175  memcpy(data_buf, cmp, readamount);
176 
177  return 0;
178 }
179 
180 /*--------------------------------------------------------------------------*/
181 
182 static int read_data_uncompressed(int fd, int row, unsigned char *data_buf,
183  int *nbytes)
184 {
185  struct fileinfo *fcb = &G__.fileinfo[fd];
186  ssize_t bufsize = fcb->cellhd.cols * fcb->nbytes;
187 
188  *nbytes = fcb->nbytes;
189 
190  if (lseek(fd, (off_t) row * bufsize, SEEK_SET) == -1)
191  return -1;
192 
193  if (read(fd, data_buf, bufsize) != bufsize)
194  return -1;
195 
196  return 0;
197 }
198 
199 /*--------------------------------------------------------------------------*/
200 
201 #ifdef HAVE_GDAL
202 static int read_data_gdal(int fd, int row, unsigned char *data_buf, int *nbytes)
203 {
204  struct fileinfo *fcb = &G__.fileinfo[fd];
205  CPLErr err;
206 
207  *nbytes = fcb->nbytes;
208 
209  err = G_gdal_raster_IO(
210  fcb->gdal->band, GF_Read, 0, row, fcb->cellhd.cols, 1, data_buf,
211  fcb->cellhd.cols, 1, fcb->gdal->type, 0, 0);
212 
213  return err == CE_None ? 0 : -1;
214 }
215 #endif
216 
217 /*--------------------------------------------------------------------------*/
218 
219 /* Actually read a row of data in */
220 
221 static int read_data(int fd, int row, unsigned char *data_buf, int *nbytes)
222 {
223  struct fileinfo *fcb = &G__.fileinfo[fd];
224 
225 #ifdef HAVE_GDAL
226  if (fcb->gdal)
227  return read_data_gdal(fd, row, data_buf, nbytes);
228 #endif
229 
230  if (!fcb->cellhd.compressed)
231  return read_data_uncompressed(fd, row, data_buf, nbytes);
232 
233  /* map is in compressed form */
234 
235  if (fcb->map_type == CELL_TYPE)
236  return read_data_compressed(fd, row, data_buf, nbytes);
237  else
238  return read_data_fp_compressed(fd, row, data_buf, nbytes);
239 }
240 
241 /*--------------------------------------------------------------------------*/
242 
243 /* copy cell file data to user buffer translated by window column mapping */
244 
245 static void cell_values_int(int fd, const unsigned char *data,
246  const COLUMN_MAPPING * cmap, int nbytes,
247  void *cell, int n)
248 {
249  CELL *c = cell;
250  COLUMN_MAPPING cmapold = 0;
251  int big = (size_t) nbytes >= sizeof(CELL);
252  int i;
253 
254  for (i = 0; i < n; i++) {
255  const unsigned char *d;
256  int neg;
257  CELL v;
258  int j;
259 
260  if (!cmap[i]) {
261  c[i] = 0;
262  continue;
263  }
264 
265  if (cmap[i] == cmapold) {
266  c[i] = c[i - 1];
267  continue;
268  }
269 
270  d = data + (cmap[i] - 1) * nbytes;
271 
272  if (big && (*d & 0x80)) {
273  neg = 1;
274  v = *d++ & 0x7f;
275  }
276  else {
277  neg = 0;
278  v = *d++;
279  }
280 
281  for (j = 1; j < nbytes; j++)
282  v = (v << 8) + *d++;
283 
284  c[i] = neg ? -v : v;
285 
286  cmapold = cmap[i];
287  }
288 }
289 
290 /*--------------------------------------------------------------------------*/
291 
292 static void cell_values_float(int fd, const unsigned char *data,
293  const COLUMN_MAPPING * cmap, int nbytes,
294  void *cell, int n)
295 {
296  struct fileinfo *fcb = &G__.fileinfo[fd];
297  FCELL *c = cell;
298  COLUMN_MAPPING cmapold = 0;
299  XDR *xdrs = &fcb->xdrstream;
300  int i;
301 
302  /* xdr stream is initialized to read from */
303  /* fcb->data in 'opencell.c' */
304  xdr_setpos(xdrs, 0);
305 
306  for (i = 0; i < n; i++) {
307  if (!cmap[i]) {
308  c[i] = 0;
309  continue;
310  }
311 
312  if (cmap[i] == cmapold) {
313  c[i] = c[i - 1];
314  continue;
315  }
316 
317  if (cmap[i] < cmapold) {
318  xdr_setpos(xdrs, 0);
319  cmapold = 0;
320  }
321 
322  while (cmapold++ != cmap[i]) /* skip */
323  if (!xdr_float(xdrs, &c[i]))
324  G_fatal_error(_("cell_values_float: xdr_float failed for index %d"),
325  i);
326 
327  cmapold--;
328  }
329 }
330 
331 /*--------------------------------------------------------------------------*/
332 
333 static void cell_values_double(int fd, const unsigned char *data,
334  const COLUMN_MAPPING * cmap, int nbytes,
335  void *cell, int n)
336 {
337  struct fileinfo *fcb = &G__.fileinfo[fd];
338  DCELL *c = cell;
339  COLUMN_MAPPING cmapold = 0;
340  XDR *xdrs = &fcb->xdrstream;
341  int i;
342 
343  /* xdr stream is initialized to read from */
344  /* fcb->data in 'opencell.c' */
345  xdr_setpos(xdrs, 0);
346 
347  for (i = 0; i < n; i++) {
348  if (!cmap[i]) {
349  c[i] = 0;
350  continue;
351  }
352 
353  if (cmap[i] == cmapold) {
354  c[i] = c[i - 1];
355  continue;
356  }
357 
358  if (cmap[i] < cmapold) {
359  xdr_setpos(xdrs, 0);
360  cmapold = 0;
361  }
362 
363  while (cmapold++ != cmap[i]) /* skip */
364  if (!xdr_double(xdrs, &c[i]))
365  G_fatal_error(_("cell_values_double: xdr_double failed for index %d"),
366  i);
367 
368  cmapold--;
369  }
370 }
371 
372 /*--------------------------------------------------------------------------*/
373 
374 /*--------------------------------------------------------------------------*/
375 
376 #ifdef HAVE_GDAL
377 
378 /*--------------------------------------------------------------------------*/
379 
380 static void gdal_values_int(int fd, const unsigned char *data,
381  const COLUMN_MAPPING *cmap, int nbytes,
382  CELL *cell, int n)
383 {
384  struct fileinfo *fcb = &G__.fileinfo[fd];
385  const unsigned char *d;
386  COLUMN_MAPPING cmapold = 0;
387  int i;
388 
389  for (i = 0; i < n; i++) {
390  if (!cmap[i]) {
391  cell[i] = 0;
392  continue;
393  }
394 
395  if (cmap[i] == cmapold) {
396  cell[i] = cell[i-1];
397  continue;
398  }
399 
400  d = data + (cmap[i] - 1) * nbytes;
401 
402  switch (fcb->gdal->type) {
403  case GDT_Byte: cell[i] = *(GByte *)d; break;
404  case GDT_Int16: cell[i] = *(GInt16 *)d; break;
405  case GDT_UInt16: cell[i] = *(GUInt16 *)d; break;
406  case GDT_Int32: cell[i] = *(GInt32 *)d; break;
407  case GDT_UInt32: cell[i] = *(GUInt32 *)d; break;
408  default:
409  /* shouldn't happen */
410  G_set_c_null_value(&cell[i], 1);
411  break;
412  }
413 
414  cmapold = cmap[i];
415  }
416 }
417 
418 /*--------------------------------------------------------------------------*/
419 
420 static void gdal_values_float(int fd, const float *data,
421  const COLUMN_MAPPING *cmap, int nbytes,
422  FCELL *cell, int n)
423 {
424  COLUMN_MAPPING cmapold = 0;
425  int i;
426 
427  for (i = 0; i < n; i++) {
428  if (!cmap[i]) {
429  cell[i] = 0;
430  continue;
431  }
432 
433  if (cmap[i] == cmapold) {
434  cell[i] = cell[i-1];
435  continue;
436  }
437 
438  cell[i] = data[cmap[i] - 1];
439 
440  cmapold = cmap[i];
441  }
442 }
443 
444 /*--------------------------------------------------------------------------*/
445 
446 static void gdal_values_double(int fd, const double *data,
447  const COLUMN_MAPPING *cmap, int nbytes,
448  DCELL *cell, int n)
449 {
450  COLUMN_MAPPING cmapold = 0;
451  int i;
452 
453  for (i = 0; i < n; i++) {
454  if (!cmap[i]) {
455  cell[i] = 0;
456  continue;
457  }
458 
459  if (cmap[i] == cmapold) {
460  cell[i] = cell[i-1];
461  continue;
462  }
463 
464  cell[i] = data[cmap[i] - 1];
465 
466  cmapold = cmap[i];
467  }
468 }
469 
470 /*--------------------------------------------------------------------------*/
471 
472 #endif
473 
474 /*--------------------------------------------------------------------------*/
475 
476 /* transfer_to_cell_XY takes bytes from fcb->data, converts these bytes with
477  the appropriate procedure (e.g. XDR or byte reordering) into type X
478  values which are put into array G__.work_buf.
479  finally the values in G__.work_buf are converted into
480  type Y and put into 'cell'.
481  if type X == type Y the intermediate step of storing the values in
482  G__.work_buf might be ommited. check the appropriate function for XY to
483  determine the procedure of conversion.
484  */
485 
486 /*--------------------------------------------------------------------------*/
487 
488 static void transfer_to_cell_XX(int fd, void *cell)
489 {
490  static void (*cell_values_type[3]) () = {
491  cell_values_int, cell_values_float, cell_values_double};
492 #ifdef HAVE_GDAL
493  static void (*gdal_values_type[3]) () = {
494  gdal_values_int, gdal_values_float, gdal_values_double};
495 #endif
496  struct fileinfo *fcb = &G__.fileinfo[fd];
497 
498 #ifdef HAVE_GDAL
499  if (fcb->gdal)
500  (gdal_values_type[fcb->map_type]) (fd, fcb->data, fcb->col_map,
501  fcb->cur_nbytes, cell,
502  G__.window.cols);
503  else
504 #endif
505  (cell_values_type[fcb->map_type]) (fd, fcb->data, fcb->col_map,
506  fcb->cur_nbytes, cell,
507  G__.window.cols);
508 }
509 
510 /*--------------------------------------------------------------------------*/
511 
512 static void transfer_to_cell_fi(int fd, void *cell)
513 {
514  struct fileinfo *fcb = &G__.fileinfo[fd];
515  int i;
516 
517  transfer_to_cell_XX(fd, G__.work_buf);
518 
519  for (i = 0; i < G__.window.cols; i++)
520  ((CELL *) cell)[i] = (fcb->col_map[i] == 0)
521  ? 0
523  ((FCELL *) G__.work_buf)[i]);
524 }
525 
526 static void transfer_to_cell_di(int fd, void *cell)
527 {
528  struct fileinfo *fcb = &G__.fileinfo[fd];
529  int i;
530 
531  transfer_to_cell_XX(fd, G__.work_buf);
532 
533  for (i = 0; i < G__.window.cols; i++)
534  ((CELL *) cell)[i] = (fcb->col_map[i] == 0)
535  ? 0
537  ((DCELL *) G__.work_buf)[i]);
538 }
539 
540 /*--------------------------------------------------------------------------*/
541 
542 static void transfer_to_cell_if(int fd, void *cell)
543 {
544  int i;
545 
546  transfer_to_cell_XX(fd, G__.work_buf);
547 
548  for (i = 0; i < G__.window.cols; i++)
549  ((FCELL *) cell)[i] = ((CELL *) G__.work_buf)[i];
550 }
551 
552 static void transfer_to_cell_df(int fd, void *cell)
553 {
554  int i;
555 
556  transfer_to_cell_XX(fd, G__.work_buf);
557 
558  for (i = 0; i < G__.window.cols; i++)
559  ((FCELL *) cell)[i] = ((DCELL *) G__.work_buf)[i];
560 }
561 
562 /*--------------------------------------------------------------------------*/
563 
564 static void transfer_to_cell_id(int fd, void *cell)
565 {
566  int i;
567 
568  transfer_to_cell_XX(fd, G__.work_buf);
569 
570  for (i = 0; i < G__.window.cols; i++)
571  ((DCELL *) cell)[i] = ((CELL *) G__.work_buf)[i];
572 }
573 
574 static void transfer_to_cell_fd(int fd, void *cell)
575 {
576  int i;
577 
578  transfer_to_cell_XX(fd, G__.work_buf);
579 
580  for (i = 0; i < G__.window.cols; i++)
581  ((DCELL *) cell)[i] = ((FCELL *) G__.work_buf)[i];
582 }
583 
584 /*--------------------------------------------------------------------------*/
585 
586 /*--------------------------------------------------------------------------*/
587 
588 /*--------------------------------------------------------------------------*/
589 /*
590  * works for all map types and doesn't consider
591  * null row corresponding to the requested row
592  */
593 static int get_map_row_nomask(int fd, void *rast, int row,
594  RASTER_MAP_TYPE data_type)
595 {
596  static void (*transfer_to_cell_FtypeOtype[3][3]) () = { {
597  transfer_to_cell_XX, transfer_to_cell_if, transfer_to_cell_id}, {
598  transfer_to_cell_fi, transfer_to_cell_XX, transfer_to_cell_fd}, {
599  transfer_to_cell_di, transfer_to_cell_df, transfer_to_cell_XX}};
600  struct fileinfo *fcb = &G__.fileinfo[fd];
601  int r;
602  int rowStatus;
603 
604  rowStatus = compute_window_row(fd, row, &r);
605 
606  if (rowStatus <= 0) {
607  fcb->cur_row = -1;
608  G_zero_raster_buf(rast, data_type);
609  return rowStatus;
610  }
611 
612  /* read cell file row if not in memory */
613  if (r != fcb->cur_row) {
614  fcb->cur_row = r;
615 
616  if (read_data(fd, fcb->cur_row, fcb->data, &fcb->cur_nbytes) < 0) {
617  G_zero_raster_buf(rast, data_type);
618 
619  if (!fcb->io_error) {
620  if (fcb->cellhd.compressed)
621  G_warning(_("Error reading compressed map <%s@%s>, row %d"),
622  fcb->name, fcb->mapset, r);
623  else
624  G_warning(_("Error reading map <%s@%s>, row %d"),
625  fcb->name, fcb->mapset, r);
626 
627  fcb->io_error = 1;
628  }
629  return -1;
630  }
631  }
632 
633  (transfer_to_cell_FtypeOtype[fcb->map_type][data_type]) (fd, rast);
634 
635  return 1;
636 }
637 
638 /*--------------------------------------------------------------------------*/
639 
640 static int get_map_row_no_reclass(int fd, void *rast, int row,
641  RASTER_MAP_TYPE data_type, int null_is_zero,
642  int with_mask)
643 {
644  int stat;
645 
646  stat = get_map_row_nomask(fd, rast, row, data_type);
647  if (stat < 0)
648  return stat;
649 
650  stat = embed_nulls(fd, rast, row, data_type, null_is_zero, with_mask);
651  if (stat < 0)
652  return stat;
653 
654  return 1;
655 }
656 
657 /*--------------------------------------------------------------------------*/
658 
659 static int get_map_row(int fd, void *rast, int row, RASTER_MAP_TYPE data_type,
660  int null_is_zero, int with_mask)
661 {
662  struct fileinfo *fcb = &G__.fileinfo[fd];
663  int size = G_raster_size(data_type);
664  void *buf;
665  int type;
666  int stat;
667  int i;
668 
669  if (fcb->reclass_flag && data_type != CELL_TYPE) {
670  buf = G__.temp_buf;
671  type = CELL_TYPE;
672  }
673  else {
674  buf = rast;
675  type = data_type;
676  }
677 
678  stat =
679  get_map_row_no_reclass(fd, buf, row, type, null_is_zero, with_mask);
680  if (stat < 0)
681  return stat;
682 
683  if (!fcb->reclass_flag)
684  return 1;
685 
686  /* if the map is reclass table, get and
687  reclass CELL row and copy results to needed type */
688 
689  do_reclass_int(fd, buf, null_is_zero);
690 
691  if (data_type == CELL_TYPE)
692  return 1;
693 
694  for (i = 0; i < G__.window.cols; i++) {
695  G_set_raster_value_c(rast, G__.temp_buf[i], data_type);
696  rast = G_incr_void_ptr(rast, size);
697  }
698 
699  return 1;
700 }
701 
702 /*--------------------------------------------------------------------------*/
703 
704 /*--------------------------------------------------------------------------*/
705 
706 /*--------------------------------------------------------------------------*/
707 
740 int G_get_map_row_nomask(int fd, CELL * buf, int row)
741 {
742  return get_map_row(fd, buf, row, CELL_TYPE, 1, 0);
743 }
744 
760 int G_get_raster_row_nomask(int fd, void *buf, int row,
761  RASTER_MAP_TYPE data_type)
762 {
763  return get_map_row(fd, buf, row, data_type, 0, 0);
764 }
765 
781 int G_get_c_raster_row_nomask(int fd, CELL * buf, int row)
782 {
783  return G_get_raster_row_nomask(fd, buf, row, CELL_TYPE);
784 }
785 
801 int G_get_f_raster_row_nomask(int fd, FCELL * buf, int row)
802 {
803  return G_get_raster_row_nomask(fd, buf, row, FCELL_TYPE);
804 }
805 
821 int G_get_d_raster_row_nomask(int fd, DCELL * buf, int row)
822 {
823  return G_get_raster_row_nomask(fd, buf, row, DCELL_TYPE);
824 }
825 
826 /*--------------------------------------------------------------------------*/
827 
848 int G_get_map_row(int fd, CELL * buf, int row)
849 {
850  return get_map_row(fd, buf, row, CELL_TYPE, 1, 1);
851 }
852 
896 int G_get_raster_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
897 {
898  return get_map_row(fd, buf, row, data_type, 0, 1);
899 }
900 
923 int G_get_c_raster_row(int fd, CELL * buf, int row)
924 {
925  return G_get_raster_row(fd, buf, row, CELL_TYPE);
926 }
927 
946 int G_get_f_raster_row(int fd, FCELL * buf, int row)
947 {
948  return G_get_raster_row(fd, buf, row, FCELL_TYPE);
949 }
950 
966 int G_get_d_raster_row(int fd, DCELL * buf, int row)
967 {
968  return G_get_raster_row(fd, buf, row, DCELL_TYPE);
969 }
970 
971 /*--------------------------------------------------------------------------*/
972 
973 /*--------------------------------------------------------------------------*/
974 
975 /*--------------------------------------------------------------------------*/
976 
977 static int open_null_read(int fd)
978 {
979  struct fileinfo *fcb = &G__.fileinfo[fd];
980  char *name, *mapset, *dummy;
981  int null_fd;
982 
983  if (fcb->null_file_exists == 0)
984  return -1;
985 
986  if (fcb->reclass_flag) {
987  name = fcb->reclass.name;
988  mapset = fcb->reclass.mapset;
989  }
990  else {
991  name = fcb->name;
992  mapset = fcb->mapset;
993  }
994 
995  dummy = G_find_file_misc("cell_misc", NULL_FILE, name, mapset);
996 
997  if (!dummy) {
998  /* G_warning("unable to find [%s]",path); */
999  fcb->null_file_exists = 0;
1000  return -1;
1001  }
1002 
1003  null_fd = G_open_old_misc("cell_misc", NULL_FILE, name, mapset);
1004  if (null_fd < 0)
1005  return -1;
1006 
1007  fcb->null_file_exists = 1;
1008 
1009  return null_fd;
1010 }
1011 
1012 static int read_null_bits(int null_fd, unsigned char *flags, int row,
1013  int cols, int fd)
1014 {
1015  off_t offset;
1016  ssize_t size;
1017  int R;
1018 
1019  if (compute_window_row(fd, row, &R) <= 0) {
1020  G__init_null_bits(flags, cols);
1021  return 1;
1022  }
1023 
1024  if (null_fd < 0)
1025  return -1;
1026 
1027  size = G__null_bitstream_size(cols);
1028  offset = (off_t) size *R;
1029 
1030  if (lseek(null_fd, offset, SEEK_SET) < 0) {
1031  G_warning(_("Error reading null row %d"), R);
1032  return -1;
1033  }
1034 
1035  if (read(null_fd, flags, size) != size) {
1036  G_warning(_("Error reading null row %d"), R);
1037  return -1;
1038  }
1039 
1040  return 1;
1041 }
1042 
1043 static void get_null_value_row_nomask(int fd, char *flags, int row)
1044 {
1045  struct fileinfo *fcb = &G__.fileinfo[fd];
1046  int i, j, null_fd;
1047 
1048  if (row > G__.window.rows || row < 0) {
1049  G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"),
1050  fcb->name, fcb->mapset, row);
1051  }
1052 
1053  if ((fcb->min_null_row > row) ||
1054  (fcb->min_null_row + NULL_ROWS_INMEM - 1 < row))
1055  /* the null row row is not in memory */
1056  {
1057  /* read in NULL_ROWS_INMEM rows from null file
1058  so that the requested row is between fcb->min_null_row
1059  and fcb->min_null_row + NULL_ROWS_INMEM */
1060 
1061  fcb->min_null_row = (row / NULL_ROWS_INMEM) * NULL_ROWS_INMEM;
1062 
1063  null_fd = open_null_read(fd);
1064 
1065  for (i = 0; i < NULL_ROWS_INMEM; i++) {
1066  /* G__.window.rows doesn't have to be a multiple of NULL_ROWS_INMEM */
1067  if (i + fcb->min_null_row >= G__.window.rows)
1068  break;
1069 
1070  if (read_null_bits(null_fd, fcb->null_work_buf,
1071  i + fcb->min_null_row, fcb->cellhd.cols,
1072  fd) < 0) {
1073  if (fcb->map_type == CELL_TYPE) {
1074  /*
1075  If can't read null row, assume that all map 0's are nulls
1076  use allocated G__.mask_buf to read map row */
1077  get_map_row_nomask(fd, (void *)G__.mask_buf,
1078  i + fcb->min_null_row, CELL_TYPE);
1079  for (j = 0; j < G__.window.cols; j++) {
1080  if (G__.mask_buf[j] == 0)
1081  flags[j] = 1;
1082  else
1083  flags[j] = 0;
1084  }
1085  }
1086  else { /* fp map */
1087 
1088  /* if can't read null row, assume that all data is valid */
1089  G_zero(flags, sizeof(char) * G__.window.cols);
1090  /* the flags row is ready now */
1091  }
1092  } /*if no null file */
1093  else {
1094  /* copy null row to flags row translated by window column mapping */
1095  /* the fcb->NULL_ROWS[row-fcb->min_null_row] has G__.window.cols bits, */
1096  /* the fcb->null_work_buf has size fcb->cellhd.cols */
1097  for (j = 0; j < G__.window.cols; j++) {
1098  if (!fcb->col_map[j])
1099  flags[j] = 1;
1100  else
1101  flags[j] = G__check_null_bit(fcb->null_work_buf,
1102  fcb->col_map[j] - 1,
1103  fcb->cellhd.cols);
1104  }
1105  }
1106  /* remember the null row for i for the future reference */
1107 
1108  /*bf-We should take of the size - or we get
1109  zeros running on their own after flags convertions -A.Sh. */
1110  fcb->NULL_ROWS[i] = G_realloc(fcb->NULL_ROWS[i],
1112  cols) + 1);
1113  if (fcb->NULL_ROWS[i] == NULL)
1114  G_fatal_error("get_null_value_row_nomask: %s",
1115  _("Unable to realloc buffer"));
1116 
1117  G__convert_01_flags(flags, fcb->NULL_ROWS[i], G__.window.cols);
1118 
1119  } /* for loop */
1120 
1121  if (null_fd > 0)
1122  close(null_fd);
1123  } /* row is not in memory */
1124 
1125  /* copy null file data translated by column mapping to user null row */
1126  /* the user requested flags row is of size G__.window.cols */
1127  G__convert_flags_01(flags, fcb->NULL_ROWS[row - fcb->min_null_row],
1128  G__.window.cols);
1129 }
1130 
1131 /*--------------------------------------------------------------------------*/
1132 
1133 #ifdef HAVE_GDAL
1134 
1135 static void get_null_value_row_gdal(int fd, char *flags, int row)
1136 {
1137  struct fileinfo *fcb = &G__.fileinfo[fd];
1138  DCELL *tmp_buf = G_allocate_d_raster_buf();
1139  int i;
1140 
1141  if (get_map_row_nomask(fd, tmp_buf, row, DCELL_TYPE) <= 0) {
1142  memset(flags, 1, G__.window.cols);
1143  G_free(tmp_buf);
1144  return;
1145  }
1146 
1147  for (i = 0; i < G__.window.cols; i++)
1148  /* note: using == won't work if the null value is NaN */
1149  flags[i] = !fcb->col_map[i] ||
1150  memcmp(&tmp_buf[i], &fcb->gdal->null_val, sizeof(DCELL)) == 0;
1151 
1152  G_free(tmp_buf);
1153 }
1154 
1155 #endif
1156 
1157 /*--------------------------------------------------------------------------*/
1158 
1159 /*--------------------------------------------------------------------------*/
1160 
1161 static void embed_mask(char *flags, int row)
1162 {
1163  int i;
1164 
1165  if (G__.auto_mask <= 0)
1166  return;
1167 
1168  if (get_map_row_nomask(G__.mask_fd, G__.mask_buf, row, CELL_TYPE) < 0)
1169  return;
1170 
1172  do_reclass_int(G__.mask_fd, G__.mask_buf, 1);
1173 
1174  for (i = 0; i < G__.window.cols; i++)
1175  if (G__.mask_buf[i] == 0)
1176  flags[i] = 1;
1177 }
1178 
1179 static void get_null_value_row(int fd, char *flags, int row, int with_mask)
1180 {
1181 #ifdef HAVE_GDAL
1182  struct fileinfo *fcb = &G__.fileinfo[fd];
1183  if (fcb->gdal)
1184  get_null_value_row_gdal(fd, flags, row);
1185  else
1186 #endif
1187  get_null_value_row_nomask(fd, flags, row);
1188 
1189  if (with_mask)
1190  embed_mask(flags, row);
1191 }
1192 
1193 static int embed_nulls(int fd, void *buf, int row, RASTER_MAP_TYPE map_type,
1194  int null_is_zero, int with_mask)
1195 {
1196  struct fileinfo *fcb = &G__.fileinfo[fd];
1197  int i;
1198 
1199  /* this is because without null file the nulls can be only due to 0's
1200  in data row or mask */
1201  if (null_is_zero && !fcb->null_file_exists
1202  && (G__.auto_mask <= 0 || !with_mask))
1203  return 1;
1204 
1205  get_null_value_row(fd, G__.null_buf, row, with_mask);
1206 
1207  for (i = 0; i < G__.window.cols; i++) {
1208  /* also check for nulls which might be already embedded by quant
1209  rules in case of fp map. */
1210  if (G__.null_buf[i] || G_is_null_value(buf, map_type)) {
1211  /* G__set_[f/d]_null_value() sets it to 0 is the embedded mode
1212  is not set and calls G_set_[f/d]_null_value() otherwise */
1213  G__set_null_value(buf, 1, null_is_zero, map_type);
1214  }
1215  buf = G_incr_void_ptr(buf, G_raster_size(map_type));
1216  }
1217 
1218  return 1;
1219 }
1220 
1221 /*--------------------------------------------------------------------------*/
1222 
1223 /*--------------------------------------------------------------------------*/
1224 
1225 /*--------------------------------------------------------------------------*/
1226 
1243 int G_get_null_value_row(int fd, char *flags, int row)
1244 {
1245  struct fileinfo *fcb = &G__.fileinfo[fd];
1246 
1247  if (!fcb->reclass_flag)
1248  get_null_value_row(fd, flags, row, 1);
1249  else {
1250  CELL *buf = G_allocate_c_raster_buf();
1251  int i;
1252 
1253  G_get_c_raster_row(fd, buf, row);
1254  for (i = 0; i < G__.window.cols; i++)
1255  flags[i] = G_is_c_null_value(&buf[i]) ? 1 : 0;
1256 
1257  G_free(buf);
1258  }
1259 
1260  return 1;
1261 }