GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
raster/open.c
Go to the documentation of this file.
1 /*!
2  * \file lib/raster/open.c
3  *
4  * \brief Raster Library - Open raster file
5  *
6  * (C) 1999-2009 by the GRASS Development Team
7  *
8  * This program is free software under the GNU General Public
9  * License (>=v2). Read the file COPYING that comes with GRASS
10  * for details.
11  *
12  * \author USACERL and many others
13  */
14 
15 #include <unistd.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <errno.h>
21 
22 #include <grass/config.h>
23 #include <grass/gis.h>
24 #include <grass/raster.h>
25 #include <grass/glocale.h>
26 
27 #include "R.h"
28 #define FORMAT_FILE "f_format"
29 #define NULL_FILE "null"
30 /* cmpressed null file */
31 #define NULLC_FILE "nullcmpr"
32 
33 static int new_fileinfo(void)
34 {
35  int oldsize = R__.fileinfo_count;
36  int newsize = oldsize;
37  int i;
38 
39  for (i = 0; i < oldsize; i++)
40  if (R__.fileinfo[i].open_mode <= 0) {
41  memset(&R__.fileinfo[i], 0, sizeof(struct fileinfo));
42  R__.fileinfo[i].open_mode = -1;
43  return i;
44  }
45 
46  if (newsize < 20)
47  newsize += 20;
48  else
49  newsize *= 2;
50 
51  R__.fileinfo = G_realloc(R__.fileinfo, newsize * sizeof(struct fileinfo));
52 
53  /* Mark all cell files as closed */
54  for (i = oldsize; i < newsize; i++) {
55  memset(&R__.fileinfo[i], 0, sizeof(struct fileinfo));
56  R__.fileinfo[i].open_mode = -1;
57  }
58 
59  R__.fileinfo_count = newsize;
60 
61  return oldsize;
62 }
63 
64 /*!
65  * \brief Open raster file
66  *
67  * Arrange for the NULL-value bitmap to be read as well as the raster
68  * map. If no NULL-value bitmap exists, arrange for the production of
69  * NULL-values based on zeros in the raster map. If the map is
70  * floating-point, arrange for quantization to integer for
71  * Rast_get_c_row(), et. al., by reading the quantization rules
72  * for the map using Rast_read_quant(). If the programmer wants to read
73  * the floating point map using uing quant rules other than the ones
74  * stored in map's quant file, he/she should call Rast_set_quant_rules()
75  * after the call to Rast_open_old().
76  *
77  * \param name map name
78  * \param open_mode mode
79  * \param map_type map type (CELL, FCELL, DCELL)
80  *
81  * \return open file descriptor ( >= 0) if successful
82  */
83 static int open_raster_new(const char *name, int open_mode,
84  RASTER_MAP_TYPE map_type);
85 
86 /*!
87  \brief Open an existing integer raster map (cell)
88 
89  Opens the existing cell file <i>name</i> in the <i>mapset</i> for
90  reading by Rast_get_row() with mapping into the current window.
91 
92  This routine opens the raster map <i>name</i> in <i>mapset</i> for
93  reading. A nonnegative file descriptor is returned if the open is
94  successful. Otherwise a diagnostic message is printed and a negative
95  value is returned. This routine does quite a bit of work. Since
96  GRASS users expect that all raster maps will be resampled into the
97  current region, the resampling index for the raster map is prepared
98  by this routine after the file is opened. The resampling is based on
99  the active module region (see also \ref The_Region}. Preparation
100  required for reading the various raster file formats (see \ref
101  Raster_File_Format for an explanation of the various raster file
102  formats) is also done.
103 
104  Diagnostics: warning message printed if open fails.
105 
106  \param name map name
107  \param mapset mapset name where raster map <i>name</i> lives
108 
109  \return nonnegative file descriptor (int)
110  */
111 int Rast_open_old(const char *name, const char *mapset)
112 {
113  int fd = Rast__open_old(name, mapset);
114 
115  /* turn on auto masking, if not already on */
117  /*
118  if(R__.auto_mask <= 0)
119  R__.mask_buf = Rast_allocate_c_buf();
120  now we don't ever free it!, so no need to allocate it (Olga)
121  */
122  /* mask_buf is used for reading mask file when mask is set and
123  for reading map rows when the null file doesn't exist */
124 
125  return fd;
126 }
127 
128 /*! \brief Lower level function, open cell files, supercell files,
129  and the mask file.
130 
131  Actions:
132  - opens the named cell file, following reclass reference if
133  named layer is a reclass layer.
134  - creates the required mapping between the data and the window
135  for use by the get_map_row family of routines.
136 
137  Diagnostics: Errors other than actual open failure will cause a
138  diagnostic to be delivered through G_warning() open failure messages
139  are left to the calling routine since the masking logic will want to
140  issue a different warning.
141 
142  Note: This routine does NOT open the mask layer. If it did we would
143  get infinite recursion. This routine is called to open the mask by
144  Rast__check_for_auto_masking() which is called by Rast_open_old().
145 
146  \param name map name
147  \param mapset mapset of cell file to be opened
148 
149  \return open file descriptor
150  */
151 int Rast__open_old(const char *name, const char *mapset)
152 {
153  struct fileinfo *fcb;
154  int cell_fd, fd;
155  char *cell_dir;
156  const char *r_name;
157  const char *r_mapset;
158  struct Cell_head cellhd;
159  int CELL_nbytes = 0; /* bytes per cell in CELL map */
160  int reclass_flag;
161  int MAP_NBYTES;
162  RASTER_MAP_TYPE MAP_TYPE;
163  struct Reclass reclass;
164  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
165  struct GDAL_link *gdal;
166  struct R_vrt *vrt;
167 
168  Rast__init();
169 
170  G_unqualified_name(name, mapset, xname, xmapset);
171  name = xname;
172  mapset = xmapset;
173 
174  if (!G_find_raster2(name, mapset))
175  G_fatal_error(_("Raster map <%s> not found"),
176  G_fully_qualified_name(name, mapset));
177 
178  /* Check for reclassification */
179  reclass_flag = Rast_get_reclass(name, mapset, &reclass);
180 
181  switch (reclass_flag) {
182  case 0:
183  r_name = name;
184  r_mapset = mapset;
185  break;
186  case 1:
187  r_name = reclass.name;
188  r_mapset = reclass.mapset;
189  if (!G_find_raster2(r_name, r_mapset))
191  _("Unable to open raster map <%s@%s> since it is a reclass "
192  "of raster map <%s@%s> which does not exist"),
193  name, mapset, r_name, r_mapset);
194  break;
195  default: /* Error reading cellhd/reclass file */
196  G_fatal_error(_("Error reading reclass file for raster map <%s>"),
197  G_fully_qualified_name(name, mapset));
198  break;
199  }
200 
201  /* read the cell header */
202  Rast_get_cellhd(r_name, r_mapset, &cellhd);
203 
204  /* now check the type */
205  MAP_TYPE = Rast_map_type(r_name, r_mapset);
206  if (MAP_TYPE < 0)
207  G_fatal_error(_("Error reading map type for raster map <%s>"),
208  G_fully_qualified_name(name, mapset));
209 
210  if (MAP_TYPE == CELL_TYPE)
211  /* set the number of bytes for CELL map */
212  {
213  CELL_nbytes = cellhd.format + 1;
214  if (CELL_nbytes < 1)
216  _("Raster map <%s@%s>: format field in header file invalid"),
217  r_name, r_mapset);
218  }
219 
220  /* compressor */
221  if (MAP_TYPE != CELL_TYPE) {
222  /* fp maps do not use RLE */
223  /* previously, compressed simply meant yes (ZLIB) or no
224  * now compressed encodes compressor type
225  * 0: not compressed
226  * 1, 2: ZLIB
227  * 3: LZ4
228  * 4: BZIP2
229  * etc */
230  if (cellhd.compressed == 1)
231  cellhd.compressed = 2;
232  }
233  /* test if compressor type is supported */
234  if (!G_check_compressor(cellhd.compressed)) {
235  G_fatal_error(_("Compression with %s is not supported in this GRASS "
236  "GIS installation"),
237  G_compressor_name(cellhd.compressed));
238  }
239 
240  if (cellhd.proj != R__.rd_window.proj)
242  _("Raster map <%s> is in different projection than current region. "
243  "Found <%s>, should be <%s>."),
244  G_fully_qualified_name(name, mapset),
245  G_projection_name(cellhd.proj),
247 
248  if (cellhd.zone != R__.rd_window.zone)
249  G_fatal_error(_("Raster map <%s> is in different zone (%d) than "
250  "current region (%d)"),
251  G_fully_qualified_name(name, mapset), cellhd.zone,
252  R__.rd_window.zone);
253 
254  /* when map is int warn if too large cell size */
255  if (MAP_TYPE == CELL_TYPE && (unsigned int)CELL_nbytes > sizeof(CELL))
256  G_fatal_error(_("Raster map <%s>: bytes per cell (%d) too large"),
257  G_fully_qualified_name(name, mapset), CELL_nbytes);
258 
259  /* record number of bytes per cell */
260  if (MAP_TYPE == FCELL_TYPE) {
261  cell_dir = "fcell";
262  MAP_NBYTES = XDR_FLOAT_NBYTES;
263  }
264  else if (MAP_TYPE == DCELL_TYPE) {
265  cell_dir = "fcell";
266  MAP_NBYTES = XDR_DOUBLE_NBYTES;
267  }
268  else { /* integer */
269  cell_dir = "cell";
270  MAP_NBYTES = CELL_nbytes;
271  }
272 
273  gdal = Rast_get_gdal_link(r_name, r_mapset);
274  vrt = Rast_get_vrt(r_name, r_mapset);
275  cell_fd = -1;
276  if (gdal) {
277 #ifdef HAVE_GDAL
278  cell_fd = -1;
279 #else
280  G_fatal_error(_("Raster map <%s@%s> is a GDAL link but GRASS is "
281  "compiled without GDAL support"),
282  r_name, r_mapset);
283 #endif
284  }
285  else if (vrt) {
286  cell_fd = -1;
287  }
288  else {
289  /* now actually open file for reading */
290  cell_fd = G_open_old(cell_dir, r_name, r_mapset);
291  if (cell_fd < 0)
292  G_fatal_error(_("Unable to open %s file for raster map <%s@%s>"),
293  cell_dir, r_name, r_mapset);
294  }
295 
296  fd = new_fileinfo();
297  fcb = &R__.fileinfo[fd];
298  fcb->data_fd = cell_fd;
299 
300  fcb->map_type = MAP_TYPE;
301 
302  /* Save cell header */
303  fcb->cellhd = cellhd;
304 
305  /* allocate null bitstream buffers for reading null rows */
306  fcb->null_fd = -1;
307  fcb->null_cur_row = -1;
308  fcb->null_bits = Rast__allocate_null_bits(cellhd.cols);
309 
310  /* mark closed */
311  fcb->open_mode = -1;
312 
313  /* save name and mapset */
314  fcb->name = G_store(name);
315  fcb->mapset = G_store(mapset);
316 
317  /* mark no data row in memory */
318  fcb->cur_row = -1;
319 
320  /* if reclass, copy reclass structure */
321  if ((fcb->reclass_flag = reclass_flag))
322  fcb->reclass = reclass;
323 
324  fcb->gdal = gdal;
325  fcb->vrt = vrt;
326  if (!gdal && !vrt) {
327  /* check for compressed data format, making initial reads if necessary
328  */
329  if (Rast__check_format(fd) < 0) {
330  close(cell_fd); /* warning issued by check_format() */
331  G_fatal_error(_("Error reading format for <%s@%s>"), r_name,
332  r_mapset);
333  }
334  }
335 
336  if (!vrt) {
337  /* create the mapping from cell file to window */
339  }
340 
341  /*
342  * allocate the data buffer
343  * number of bytes per cell is cellhd.format+1
344  */
345 
346  /* for reading fcb->data is allocated to be fcb->cellhd.cols * fcb->nbytes
347  (= XDR_FLOAT/DOUBLE_NBYTES) */
348  fcb->data = (unsigned char *)G_calloc(fcb->cellhd.cols, MAP_NBYTES);
349 
350  /* initialize/read in quant rules for float point maps */
351  if (fcb->map_type != CELL_TYPE) {
352  if (fcb->reclass_flag)
354  &(fcb->quant));
355  else
356  Rast_read_quant(fcb->name, fcb->mapset, &(fcb->quant));
357  }
358 
359  /* now mark open for read: this must follow create_window_mapping() */
360  fcb->open_mode = OPEN_OLD;
361  fcb->io_error = 0;
362  fcb->map_type = MAP_TYPE;
363  fcb->nbytes = MAP_NBYTES;
364  fcb->null_row_ptr = NULL;
365 
366  if (!gdal && !vrt) {
367  /* First, check for compressed null file */
368  fcb->null_fd =
369  G_open_old_misc("cell_misc", NULL_FILE, r_name, r_mapset);
370  if (fcb->null_fd < 0) {
371  fcb->null_fd =
372  G_open_old_misc("cell_misc", NULLC_FILE, r_name, r_mapset);
373  if (fcb->null_fd >= 0) {
374  fcb->null_row_ptr =
375  G_calloc(fcb->cellhd.rows + 1, sizeof(off_t));
376  if (Rast__read_null_row_ptrs(fd, fcb->null_fd) < 0) {
377  close(fcb->null_fd);
378  fcb->null_fd = -1;
379  G_free(fcb->null_row_ptr);
380  fcb->null_row_ptr = NULL;
381  }
382  }
383  }
384  fcb->null_file_exists = fcb->null_fd >= 0;
385  }
386 
387  return fd;
388 }
389 
390 /*!
391  \brief Opens a new cell file in a database (compressed)
392 
393  Opens a new cell file <i>name</i> in the current mapset for writing
394  by Rast_put_row().
395 
396  The file is created and filled with no data it is assumed that the
397  new cell file is to conform to the current window.
398 
399  The file must be written sequentially. Use Rast_open_new_random()
400  for non sequential writes.
401 
402  Note: the open actually creates a temporary file Rast_close() will
403  move the temporary file to the cell file and write out the necessary
404  support files (cellhd, cats, hist, etc.).
405 
406  Diagnostics: warning message printed if open fails
407 
408  Warning: calls to Rast_set_window() made after opening a new cell file
409  may create confusion and should be avoided the new cell file will be
410  created to conform to the window at the time of the open.
411 
412  \param name map name
413 
414  \return open file descriptor ( >= 0) if successful
415  \return negative integer if error
416  */
417 int Rast_open_c_new(const char *name)
418 {
419  return open_raster_new(name, OPEN_NEW_COMPRESSED, CELL_TYPE);
420 }
421 
422 /*!
423  \brief Opens a new cell file in a database (uncompressed)
424 
425  See also Rast_open_new().
426 
427  \param name map name
428 
429  \return open file descriptor ( >= 0) if successful
430  \return negative integer if error
431  */
433 {
434  return open_raster_new(name, OPEN_NEW_UNCOMPRESSED, CELL_TYPE);
435 }
436 
437 /*!
438  \brief Save histogram for newly create raster map (cell)
439 
440  If newly created cell files should have histograms, set flag=1
441  otherwise set flag=0. Applies to subsequent opens.
442 
443  \param flag flag indicator
444  */
445 void Rast_want_histogram(int flag)
446 {
447  R__.want_histogram = flag;
448 }
449 
450 /*!
451  \brief Sets the format for subsequent opens on new integer cell files
452  (uncompressed and random only).
453 
454  Warning: subsequent put_row calls will only write n+1 bytes per
455  cell. If the data requires more, the cell file will be written
456  incorrectly (but with n+1 bytes per cell)
457 
458  When writing float map: format is -1
459 
460  \param n format
461  */
463 /* sets the format for integer raster map */
464 {
465  R__.nbytes = n + 1;
466  if (R__.nbytes <= 0)
467  R__.nbytes = 1;
468  if (R__.nbytes > (int)sizeof(CELL))
469  R__.nbytes = sizeof(CELL);
470 }
471 
472 /*!
473  \brief Get cell value format
474 
475  \param v cell
476 
477  \return cell format
478  */
480 {
481  unsigned int i;
482 
483  if (v >= 0)
484  for (i = 0; i < sizeof(CELL); i++)
485  if (!(v /= 256))
486  return i;
487  return sizeof(CELL) - 1;
488 }
489 
490 /*!
491  \brief Opens new fcell file in a database
492 
493  Opens a new floating-point map <i>name</i> in the current mapset for
494  writing. The type of the file (i.e. either double or float) is
495  determined and fixed at this point. The default is FCELL_TYPE. In
496  order to change this default
497 
498  Use Rast_set_fp_type() where type is one of DCELL_TYPE or FCELL_TYPE.
499 
500  See warnings and notes for Rast_open_new().
501 
502  \param name map name
503 
504  \return nonnegative file descriptor (int)
505  */
506 int Rast_open_fp_new(const char *name)
507 {
508  return open_raster_new(name, OPEN_NEW_COMPRESSED, R__.fp_type);
509 }
510 
511 /*!
512  \brief Opens new fcell file in a database (uncompressed)
513 
514  See Rast_open_fp_new() for details.
515 
516  \param name map name
517 
518  \return nonnegative file descriptor (int)
519  */
521 {
522  return open_raster_new(name, OPEN_NEW_UNCOMPRESSED, R__.fp_type);
523 }
524 
525 #ifdef HAVE_GDAL
526 static int open_raster_new_gdal(char *map, char *mapset,
527  RASTER_MAP_TYPE map_type)
528 {
529  int fd;
530  struct fileinfo *fcb;
531 
532  fd = new_fileinfo();
533  fcb = &R__.fileinfo[fd];
534  fcb->data_fd = -1;
535 
536  /* mark closed */
537  fcb->map_type = map_type;
538  fcb->open_mode = -1;
539 
540  fcb->gdal = Rast_create_gdal_link(map, map_type);
541  if (!fcb->gdal)
542  G_fatal_error(_("Unable to create GDAL link"));
543 
544  fcb->cellhd = R__.wr_window;
545  fcb->cellhd.compressed = 0;
546  fcb->nbytes = Rast_cell_size(fcb->map_type);
547  /* for writing fcb->data is allocated to be R__.wr_window.cols *
548  sizeof(CELL or DCELL or FCELL) */
549  fcb->data = G_calloc(R__.wr_window.cols, fcb->nbytes);
550 
551  fcb->name = map;
552  fcb->mapset = mapset;
553  fcb->cur_row = 0;
554 
555  fcb->row_ptr = NULL;
556  fcb->temp_name = NULL;
557  fcb->null_temp_name = NULL;
558  fcb->null_cur_row = 0;
559  fcb->null_bits = NULL;
560  fcb->null_fd = -1;
561  fcb->null_row_ptr = NULL;
562 
563  if (fcb->map_type != CELL_TYPE)
564  Rast_quant_init(&(fcb->quant));
565 
566  /* init cell stats */
567  /* now works only for int maps */
568  if (fcb->map_type == CELL_TYPE)
569  if ((fcb->want_histogram = R__.want_histogram))
571 
572  /* init range and if map is double/float init d/f_range */
573  Rast_init_range(&fcb->range);
574 
575  if (fcb->map_type != CELL_TYPE)
577 
578  /* mark file as open for write */
580  fcb->io_error = 0;
581 
582  return fd;
583 }
584 #endif /* HAVE_GDAL */
585 
586 static int open_raster_new(const char *name, int open_mode,
588 {
589  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
590  struct fileinfo *fcb;
591  int fd, cell_fd;
592  char *tempname;
593  char *map;
594  char *mapset;
595  const char *cell_dir;
596  int nbytes;
597 
598  Rast__init();
599 
600  switch (map_type) {
601  case CELL_TYPE:
602  cell_dir = "cell";
603  nbytes = R__.nbytes;
604  break;
605  case FCELL_TYPE:
607  cell_dir = "fcell";
608  break;
609  case DCELL_TYPE:
611  cell_dir = "fcell";
612  break;
613  default:
614  G_fatal_error(_("Invalid map type <%d>"), map_type);
615  break;
616  }
617 
618  if (G_unqualified_name(name, G_mapset(), xname, xmapset) < 0)
619  G_fatal_error(_("Raster map <%s> is not in the current mapset (%s)"),
620  name, G_mapset());
621  map = G_store(xname);
622  mapset = G_store(xmapset);
623 
624  /* check for legal grass name */
625  if (G_legal_filename(map) < 0)
626  G_fatal_error(_("<%s> is an illegal file name"), map);
627 
628 #ifdef HAVE_GDAL
629  if (G_find_file2("", "GDAL", G_mapset()))
630  return open_raster_new_gdal(map, mapset, map_type);
631 #endif
632 
633  /* open a tempfile name */
634  tempname = G_tempfile();
635  cell_fd = creat(tempname, 0666);
636  if (cell_fd < 0) {
637  int err = errno;
638 
639  G_free(mapset);
640  G_free(tempname);
641  G_free(map);
642  G_fatal_error(_("No temp files available: %s"), strerror(err));
643  }
644 
645  fd = new_fileinfo();
646  fcb = &R__.fileinfo[fd];
647  fcb->data_fd = cell_fd;
648 
649  /*
650  * since we are bypassing the normal open logic
651  * must create the cell element
652  */
653  G_make_mapset_object_group(cell_dir);
654 
655  /* mark closed */
656  fcb->map_type = map_type;
657  fcb->open_mode = -1;
658  fcb->gdal = NULL;
659  fcb->vrt = NULL;
660 
661  /* for writing fcb->data is allocated to be R__.wr_window.cols *
662  sizeof(CELL or DCELL or FCELL) */
663  fcb->data = (unsigned char *)G_calloc(R__.wr_window.cols,
664  Rast_cell_size(fcb->map_type));
665 
666  /*
667  * copy current window into cell header
668  * set format to cell/supercell
669  * for compressed writing
670  * allocate space to hold the row address array
671  */
672  fcb->cellhd = R__.wr_window;
673 
674  /* change open_mode to OPEN_NEW_UNCOMPRESSED if R__.compression_type == 0 ?
675  */
676 
677  if (open_mode == OPEN_NEW_COMPRESSED && fcb->map_type == CELL_TYPE) {
678  fcb->row_ptr = G_calloc(fcb->cellhd.rows + 1, sizeof(off_t));
679  G_zero(fcb->row_ptr, (fcb->cellhd.rows + 1) * sizeof(off_t));
682 
683  fcb->nbytes = 1; /* to the minimum */
684  }
685  else {
686  fcb->nbytes = nbytes;
688  fcb->row_ptr = G_calloc(fcb->cellhd.rows + 1, sizeof(off_t));
689  G_zero(fcb->row_ptr, (fcb->cellhd.rows + 1) * sizeof(off_t));
692  }
693  else
694  fcb->cellhd.compressed = 0;
695 
696  if (fcb->map_type != CELL_TYPE) {
697  Rast_quant_init(&(fcb->quant));
698  }
699  }
700  if (open_mode == OPEN_NEW_COMPRESSED && fcb->map_type != CELL_TYPE &&
701  fcb->cellhd.compressed == 1) {
702  /* fp maps do not use RLE */
703  fcb->cellhd.compressed = 2;
704  }
705 
706  /* save name and mapset, and tempfile name */
707  fcb->name = map;
708  fcb->mapset = mapset;
709  fcb->temp_name = tempname;
710 
711  /* next row to be written (in order) is zero */
712  fcb->cur_row = 0;
713 
714  /* open a null tempfile name */
715  tempname = G_tempfile();
716  fcb->null_fd = creat(tempname, 0666);
717  if (fcb->null_fd < 0) {
718  int err = errno;
719 
720  G_free(tempname);
721  G_free(fcb->name);
722  G_free(fcb->mapset);
723  G_free(fcb->temp_name);
724  close(cell_fd);
725  G_fatal_error(_("No temp files available: %s"), strerror(err));
726  }
727 
728  fcb->null_temp_name = tempname;
729 
730  fcb->null_row_ptr = NULL;
731  if (R__.compress_nulls) {
732  fcb->null_row_ptr = G_calloc(fcb->cellhd.rows + 1, sizeof(off_t));
733  G_zero(fcb->null_row_ptr, (fcb->cellhd.rows + 1) * sizeof(off_t));
735  }
736 
737  /* next row to be written (in order) is zero */
738  fcb->null_cur_row = 0;
739 
740  /* allocate null bitstream buffer for writing */
742 
743  /* init cell stats */
744  /* now works only for int maps */
745  if (fcb->map_type == CELL_TYPE)
746  if ((fcb->want_histogram = R__.want_histogram))
748 
749  /* init range and if map is double/float init d/f_range */
750  Rast_init_range(&fcb->range);
751 
752  if (fcb->map_type != CELL_TYPE)
754 
755  /* mark file as open for write */
756  fcb->open_mode = open_mode;
757  fcb->io_error = 0;
758 
759  return fd;
760 }
761 
762 int Rast__open_null_write(const char *name)
763 {
764  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
765  struct fileinfo *fcb;
766  int fd;
767  char *tempname;
768  char *map;
769  char *mapset;
770 
771  Rast__init();
772 
773  if (!G_find_raster2(name, G_mapset()))
775  _("Raster map <%s> does not exist in the current mapset (%s)"),
776  name, G_mapset());
777 
778  if (G_unqualified_name(name, G_mapset(), xname, xmapset) < 0)
779  G_fatal_error(_("Raster map <%s> is not in the current mapset (%s)"),
780  name, G_mapset());
781  map = G_store(xname);
782  mapset = G_store(xmapset);
783 
784  fd = new_fileinfo();
785  fcb = &R__.fileinfo[fd];
786 
787  G_zero(fcb, sizeof(*fcb));
788 
789  fcb->name = map;
790  fcb->mapset = mapset;
791 
792  Rast_get_cellhd(map, mapset, &fcb->cellhd);
793 
794  /* open a null tempfile name */
795  tempname = G_tempfile();
796  fcb->null_fd = creat(tempname, 0666);
797  if (fcb->null_fd < 0) {
798  int err = errno;
799 
800  G_free(tempname);
801  G_free(fcb->name);
802  G_free(fcb->mapset);
803  G_fatal_error(_("No temp files available: %s"), strerror(err));
804  }
805  fcb->null_temp_name = tempname;
806 
807  if (R__.compress_nulls) {
808  fcb->null_row_ptr = G_calloc(fcb->cellhd.rows + 1, sizeof(off_t));
809  G_zero(fcb->null_row_ptr, (fcb->cellhd.rows + 1) * sizeof(off_t));
811  }
812 
813  /* allocate null bitstream buffer for writing */
815 
816  return fd;
817 }
818 
819 /*!
820  \brief Set raster map floating-point data format.
821 
822  This controls the storage type for floating-point maps. It affects
823  subsequent calls to G_open_fp_map_new(). The <i>type</i> must be
824  one of FCELL_TYPE (float) or DCELL_TYPE (double). The use of this
825  routine by applications is discouraged since its use would override
826  user preferences.
827 
828  \param type raster data type
829 
830  \return void
831  */
833 {
834  Rast__init();
835 
836  switch (map_type) {
837  case FCELL_TYPE:
838  case DCELL_TYPE:
839  R__.fp_type = map_type;
840  break;
841  default:
842  G_fatal_error(_("Rast_set_fp_type(): can only be called with "
843  "FCELL_TYPE or DCELL_TYPE"));
844  break;
845  }
846 }
847 
848 /*!
849  \brief Check if raster map is floating-point
850 
851  Returns true (1) if raster map <i>name</i> in <i>mapset</i>
852  is a floating-point dataset; false(0) otherwise.
853 
854  \param name map name
855  \param mapset mapset name
856 
857  \return 1 floating-point
858  \return 0 int
859  */
860 int Rast_map_is_fp(const char *name, const char *mapset)
861 {
862  char path[GPATH_MAX];
863  const char *xmapset;
864 
865  xmapset = G_find_raster2(name, mapset);
866  if (!xmapset)
867  G_fatal_error(_("Raster map <%s> not found"),
869 
870  G_file_name(path, "fcell", name, xmapset);
871  if (access(path, 0) == 0)
872  return 1;
873 
874  G_file_name(path, "g3dcell", name, xmapset);
875  if (access(path, 0) == 0)
876  return 1;
877 
878  return 0;
879 }
880 
881 /*!
882  \brief Determine raster data type
883 
884  Determines if the raster map is floating point or integer. Returns
885  DCELL_TYPE for double maps, FCELL_TYPE for float maps, CELL_TYPE for
886  integer maps, -1 if error has occurred
887 
888  \param name map name
889  \param mapset mapset where map <i>name</i> lives
890 
891  \return raster data type
892  */
893 RASTER_MAP_TYPE Rast_map_type(const char *name, const char *mapset)
894 {
895  char path[GPATH_MAX];
896  const char *xmapset;
897 
898  xmapset = G_find_raster2(name, mapset);
899  if (!xmapset) {
900  if (mapset && *mapset)
901  G_fatal_error(_("Raster map <%s> not found in mapset <%s>"), name,
902  mapset);
903  else
904  G_fatal_error(_("Raster map <%s> not found"), name);
905  }
906 
907  G_file_name(path, "fcell", name, xmapset);
908 
909  if (access(path, 0) == 0)
910  return Rast__check_fp_type(name, xmapset);
911 
912  G_file_name(path, "g3dcell", name, xmapset);
913 
914  if (access(path, 0) == 0)
915  return DCELL_TYPE;
916 
917  return CELL_TYPE;
918 }
919 
920 /*!
921  \brief Determine raster type from descriptor
922 
923  Determines if the raster map is floating point or integer. Returns
924  DCELL_TYPE for double maps, FCELL_TYPE for float maps, CELL_TYPE for
925  integer maps, -1 if error has occurred
926 
927  \param fd file descriptor
928 
929  \return raster data type
930  */
932 {
933  struct fileinfo *fcb = &R__.fileinfo[fd];
934 
935  return fcb->map_type;
936 }
937 
938 /*!
939  \brief Determines whether the floating points cell file has double or float
940  type
941 
942  \param name map name
943  \param mapset mapset where map <i>name</i> lives
944 
945  \return raster type (fcell, dcell)
946  */
948 {
949  char path[GPATH_MAX];
950  struct Key_Value *format_keys;
951  const char *str, *str1;
952  RASTER_MAP_TYPE map_type;
953  const char *xmapset;
954 
955  xmapset = G_find_raster2(name, mapset);
956  if (!xmapset)
957  G_fatal_error(_("Raster map <%s> not found"),
958  G_fully_qualified_name(name, mapset));
959 
960  G_file_name_misc(path, "cell_misc", FORMAT_FILE, name, xmapset);
961 
962  if (access(path, 0) != 0)
963  G_fatal_error(_("Unable to find '%s'"), path);
964 
965  format_keys = G_read_key_value_file(path);
966 
967  if ((str = G_find_key_value("type", format_keys)) != NULL) {
968  if (strcmp(str, "double") == 0)
969  map_type = DCELL_TYPE;
970  else if (strcmp(str, "float") == 0)
971  map_type = FCELL_TYPE;
972  else {
973  G_free_key_value(format_keys);
974  G_fatal_error(_("Invalid type: field '%s' in file '%s'"), str,
975  path);
976  }
977  }
978  else {
979  G_free_key_value(format_keys);
980  G_fatal_error(_("Missing type: field in file '%s'"), path);
981  }
982 
983  if ((str1 = G_find_key_value("byte_order", format_keys)) != NULL) {
984  if (strcmp(str1, "xdr") != 0)
985  G_warning(_("Raster map <%s> is not xdr: byte_order: %s"), name,
986  str);
987  /* here read and translate byte order if not using xdr */
988  }
989  G_free_key_value(format_keys);
990  return map_type;
991 }
992 
993 /*!
994  \brief Opens a new raster map
995 
996  Opens a new raster map of type <i>wr_type</i>
997 
998  See warnings and notes for Rast_open_new().
999 
1000  Supported data types:
1001  - CELL_TYPE
1002  - FCELL_TYPE
1003  - DCELL_TYPE
1004 
1005  On CELL_TYPE calls Rast_open_new() otherwise Rast_open_fp_new().
1006 
1007  \param name map name
1008  \param wr_type raster data type
1009 
1010  \return nonnegative file descriptor (int)
1011  */
1012 int Rast_open_new(const char *name, RASTER_MAP_TYPE wr_type)
1013 {
1014  return open_raster_new(name, OPEN_NEW_COMPRESSED, wr_type);
1015 }
1016 
1017 /*!
1018  \brief Opens a new raster map (uncompressed)
1019 
1020  See Rast_open_new().
1021 
1022  \param name map name
1023  \param wr_type raster data type
1024 
1025  \return nonnegative file descriptor (int)
1026  */
1028 {
1029  return open_raster_new(name, OPEN_NEW_UNCOMPRESSED, wr_type);
1030 }
1031 
1032 /*!
1033  \brief Sets quant translation rules for raster map opened for
1034  reading.
1035 
1036  Returned by Rast_open_old(). After calling this function,
1037  Rast_get_c_row() and Rast_get_c_row() will use rules defined by q
1038  (instead of using rules defined in map's quant file) to convert floats to
1039  ints.
1040 
1041  \param fd file descriptor (cell file)
1042  \param q pointer to Quant structure
1043 
1044  \return void
1045  */
1046 void Rast_set_quant_rules(int fd, struct Quant *q)
1047 {
1048  struct fileinfo *fcb = &R__.fileinfo[fd];
1049  CELL cell;
1050  DCELL dcell;
1051  struct Quant_table *p;
1052 
1053  if (fcb->open_mode != OPEN_OLD)
1054  G_fatal_error(_("Rast_set_quant_rules() can be called only for "
1055  "raster maps opened for reading"));
1056 
1057  /* copy all info from q to fcb->quant) */
1058  Rast_quant_init(&fcb->quant);
1059  if (q->truncate_only) {
1060  Rast_quant_truncate(&fcb->quant);
1061  return;
1062  }
1063 
1064  for (p = &(q->table[q->nofRules - 1]); p >= q->table; p--)
1065  Rast_quant_add_rule(&fcb->quant, p->dLow, p->dHigh, p->cLow, p->cHigh);
1066  if (Rast_quant_get_neg_infinite_rule(q, &dcell, &cell) > 0)
1067  Rast_quant_set_neg_infinite_rule(&fcb->quant, dcell, cell);
1068  if (Rast_quant_get_pos_infinite_rule(q, &dcell, &cell) > 0)
1069  Rast_quant_set_pos_infinite_rule(&fcb->quant, dcell, cell);
1070 }
#define OPEN_NEW_COMPRESSED
Definition: R.h:107
#define OPEN_NEW_UNCOMPRESSED
Definition: R.h:108
#define XDR_FLOAT_NBYTES
Definition: R.h:7
#define OPEN_OLD
Definition: R.h:106
#define XDR_DOUBLE_NBYTES
Definition: R.h:8
#define NULL
Definition: ccmath.h:32
char * G_file_name_misc(char *, const char *, const char *, const char *, const char *)
Builds full path names to GIS misc data files.
Definition: file_name.c:101
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:147
#define G_realloc(p, n)
Definition: defs/gis.h:96
int G_unqualified_name(const char *, const char *, char *, char *)
Returns unqualified map name (without @ mapset)
Definition: nme_in_mps.c:134
const char * G_find_file2(const char *, const char *, const char *)
Searches for a file from the mapset search list or in a specified mapset. (look but don't touch)
Definition: find_file.c:234
#define G_calloc(m, n)
Definition: defs/gis.h:95
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition: file_name.c:61
int G_legal_filename(const char *)
Check for legal database file name.
Definition: legal_name.c:34
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition: key_value1.c:85
int G_open_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition: open_misc.c:132
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition: mapset_msc.c:75
const char * G_find_raster2(const char *, const char *)
Find a raster map (look but don't touch)
Definition: find_rast.c:76
char * G_tempfile(void)
Returns a temporary file name.
Definition: tempfile.c:62
int G_open_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:169
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
Definition: key_value1.c:104
char * G_compressor_name(int)
Definition: compress.c:118
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
const char * G_projection_name(int)
Get projection name.
Definition: proj2.c:55
int G_check_compressor(int)
Definition: compress.c:140
struct Key_Value * G_read_key_value_file(const char *)
Read key/values pairs from file.
Definition: key_value3.c:55
char * G_fully_qualified_name(const char *, const char *)
Get fully qualified element name.
Definition: nme_in_mps.c:101
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
int Rast__read_null_row_ptrs(int, int)
int Rast_quant_get_neg_infinite_rule(const struct Quant *, DCELL *, CELL *)
Returns in "dLeft" and "c" the rule values.
Definition: quant.c:390
int Rast__check_for_auto_masking(void)
Checks for auto masking.
Definition: auto_mask.c:33
int Rast_get_reclass(const char *, const char *, struct Reclass *)
Get reclass.
Definition: reclass.c:140
struct R_vrt * Rast_get_vrt(const char *, const char *)
Definition: vrt.c:47
int Rast__check_format(int)
Definition: raster/format.c:64
void Rast_quant_set_pos_infinite_rule(struct Quant *, DCELL, CELL)
Defines a rule for values "dRight" and larger.
Definition: quant.c:412
int Rast_read_quant(const char *, const char *, struct Quant *)
Reads quantization rules for name in mapset and stores them in the quantization structure....
Definition: quant_rw.c:187
void Rast_quant_set_neg_infinite_rule(struct Quant *, DCELL, CELL)
Defines a rule for values "dLeft" and smaller.
Definition: quant.c:364
int Rast__write_row_ptrs(int)
struct GDAL_link * Rast_create_gdal_link(const char *, RASTER_MAP_TYPE)
Create GDAL settings for given raster map.
Definition: gdal.c:244
unsigned char * Rast__allocate_null_bits(int)
Allocates memory for null bits.
Definition: alloc_cell.c:133
int Rast__write_null_row_ptrs(int, int)
void Rast_quant_add_rule(struct Quant *, DCELL, DCELL, CELL, CELL)
Adds a new rule to the set of quantization rules.
Definition: quant.c:469
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition: alloc_cell.c:37
void Rast_init_range(struct Range *)
Initialize range structure.
Definition: raster/range.c:711
int Rast_quant_get_pos_infinite_rule(const struct Quant *, DCELL *, CELL *)
Returns in "dRight" and "c" the rule values.
Definition: quant.c:438
void Rast__init(void)
Definition: raster/init.c:61
void Rast_get_cellhd(const char *, const char *, struct Cell_head *)
Read the raster header.
Definition: get_cellhd.c:41
void Rast_quant_init(struct Quant *)
Initialize the structure.
Definition: quant.c:175
struct GDAL_link * Rast_get_gdal_link(const char *, const char *)
Get GDAL link settings for given raster map.
Definition: gdal.c:61
void Rast_init_fp_range(struct FPRange *)
Initialize fp range.
Definition: raster/range.c:763
void Rast_quant_truncate(struct Quant *)
Sets the quant rules to perform simple truncation on floats.
Definition: quant.c:217
void Rast_init_cell_stats(struct Cell_stats *)
Initialize cell stats.
Definition: cell_stats.c:39
void Rast__create_window_mapping(int)
Create window mapping.
Header file for msvc/fcntl.c.
#define creat
Definition: fcntl.h:34
#define GMAPSET_MAX
Definition: gis.h:197
#define GPATH_MAX
Definition: gis.h:199
#define GNAME_MAX
Definition: gis.h:196
double DCELL
Definition: gis.h:635
int CELL
Definition: gis.h:634
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
int Rast__open_old(const char *name, const char *mapset)
Lower level function, open cell files, supercell files, and the mask file.
Definition: raster/open.c:151
#define NULL_FILE
Definition: raster/open.c:29
void Rast_set_fp_type(RASTER_MAP_TYPE map_type)
Set raster map floating-point data format.
Definition: raster/open.c:832
int Rast__open_null_write(const char *name)
Definition: raster/open.c:762
int Rast_get_cell_format(CELL v)
Get cell value format.
Definition: raster/open.c:479
int Rast_open_new(const char *name, RASTER_MAP_TYPE wr_type)
Opens a new raster map.
Definition: raster/open.c:1012
void Rast_set_quant_rules(int fd, struct Quant *q)
Sets quant translation rules for raster map opened for reading.
Definition: raster/open.c:1046
void Rast_want_histogram(int flag)
Save histogram for newly create raster map (cell)
Definition: raster/open.c:445
RASTER_MAP_TYPE Rast_get_map_type(int fd)
Determine raster type from descriptor.
Definition: raster/open.c:931
void Rast_set_cell_format(int n)
Sets the format for subsequent opens on new integer cell files (uncompressed and random only).
Definition: raster/open.c:462
int Rast_open_c_new_uncompressed(const char *name)
Opens a new cell file in a database (uncompressed)
Definition: raster/open.c:432
int Rast_open_fp_new_uncompressed(const char *name)
Opens new fcell file in a database (uncompressed)
Definition: raster/open.c:520
int Rast_open_old(const char *name, const char *mapset)
Open an existing integer raster map (cell)
Definition: raster/open.c:111
#define NULLC_FILE
Definition: raster/open.c:31
RASTER_MAP_TYPE Rast__check_fp_type(const char *name, const char *mapset)
Determines whether the floating points cell file has double or float type.
Definition: raster/open.c:947
int Rast_open_fp_new(const char *name)
Opens new fcell file in a database.
Definition: raster/open.c:506
int Rast_open_c_new(const char *name)
Opens a new cell file in a database (compressed)
Definition: raster/open.c:417
int Rast_open_new_uncompressed(const char *name, RASTER_MAP_TYPE wr_type)
Opens a new raster map (uncompressed)
Definition: raster/open.c:1027
int Rast_map_is_fp(const char *name, const char *mapset)
Check if raster map is floating-point.
Definition: raster/open.c:860
RASTER_MAP_TYPE Rast_map_type(const char *name, const char *mapset)
Determine raster data type.
Definition: raster/open.c:893
#define FORMAT_FILE
Definition: raster/open.c:28
#define FCELL_TYPE
Definition: raster.h:12
#define DCELL_TYPE
Definition: raster.h:13
#define CELL_TYPE
Definition: raster.h:11
int RASTER_MAP_TYPE
Definition: raster.h:25
2D/3D raster map header (used also for region)
Definition: gis.h:446
int compressed
Compression mode (raster header only)
Definition: gis.h:459
int format
Max number of bytes per raster data value minus 1 (raster header only)
Definition: gis.h:452
int zone
Projection zone (UTM)
Definition: gis.h:480
int rows
Number of rows for 2D data.
Definition: gis.h:461
int cols
Number of columns for 2D data.
Definition: gis.h:465
int proj
Projection code.
Definition: gis.h:478
Definition: gis.h:534
DCELL dLow
Definition: raster.h:74
CELL cHigh
Definition: raster.h:77
CELL cLow
Definition: raster.h:76
DCELL dHigh
Definition: raster.h:75
Definition: raster.h:80
int truncate_only
Definition: raster.h:81
int nofRules
Definition: raster.h:89
struct Quant_table * table
Definition: raster.h:102
Definition: R.h:87
int compress_nulls
Definition: R.h:94
struct fileinfo * fileinfo
Definition: R.h:101
int compression_type
Definition: R.h:93
int want_histogram
Definition: R.h:91
int fileinfo_count
Definition: R.h:100
RASTER_MAP_TYPE fp_type
Definition: R.h:88
int nbytes
Definition: R.h:92
struct Cell_head wr_window
Definition: R.h:98
struct Cell_head rd_window
Definition: R.h:97
Definition: R.h:46
Definition: raster.h:31
char * mapset
Definition: raster.h:33
char * name
Definition: raster.h:32
Definition: R.h:53
off_t * row_ptr
Definition: R.h:62
int data_fd
Definition: R.h:81
char * mapset
Definition: R.h:77
struct Quant quant
Definition: R.h:79
RASTER_MAP_TYPE map_type
Definition: R.h:72
int want_histogram
Definition: R.h:60
unsigned char * null_bits
Definition: R.h:70
struct R_vrt * vrt
Definition: R.h:83
struct FPRange fp_range
Definition: R.h:59
int null_fd
Definition: R.h:69
struct Cell_head cellhd
Definition: R.h:55
off_t * null_row_ptr
Definition: R.h:82
struct Reclass reclass
Definition: R.h:56
int cur_row
Definition: R.h:65
int reclass_flag
Definition: R.h:61
struct GDAL_link * gdal
Definition: R.h:80
int io_error
Definition: R.h:78
int open_mode
Definition: R.h:54
int null_file_exists
Definition: R.h:75
unsigned char * data
Definition: R.h:68
char * name
Definition: R.h:76
char * temp_name
Definition: R.h:73
struct Cell_stats statf
Definition: R.h:57
int null_cur_row
Definition: R.h:66
char * null_temp_name
Definition: R.h:74
struct Range range
Definition: R.h:58
int nbytes
Definition: R.h:71
Definition: path.h:15
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:216
#define access
Definition: unistd.h:7
#define close
Definition: unistd.h:8