GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
raster/get_row.c
Go to the documentation of this file.
1/*!
2 \file lib/raster/get_row.c
3
4 \brief Raster library - Get raster row
5
6 (C) 2003-2009 by the GRASS Development Team
7
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
10
11 \author Original author CERL
12 */
13
14#include <stdint.h>
15#include <string.h>
16#include <unistd.h>
17#include <sys/types.h>
18#include <errno.h>
19
20#include <grass/config.h>
21#include <grass/raster.h>
22#include <grass/glocale.h>
23
24#include "R.h"
25
26static void embed_nulls(int, void *, int, RASTER_MAP_TYPE, int, int);
27
28static int compute_window_row(int fd, int row, int *cellRow)
29{
30 struct fileinfo *fcb = &R__.fileinfo[fd];
31 double f;
32 int r;
33
34 /* check for row in window */
35 if (row < 0 || row >= R__.rd_window.rows) {
36 G_fatal_error(_("Reading raster map <%s@%s> request for row %d is "
37 "outside region"),
38 fcb->name, fcb->mapset, row);
39 }
40
41 /* convert window row to cell file row */
42 f = row * fcb->C1 + fcb->C2;
43 r = (int)f;
44 if (f < r) /* adjust for rounding up of negatives */
45 r--;
46
47 if (r < 0 || r >= fcb->cellhd.rows)
48 return 0;
49
50 *cellRow = r;
51
52 return 1;
53}
54
55static void do_reclass_int(int fd, void *cell, int null_is_zero)
56{
57 struct fileinfo *fcb = &R__.fileinfo[fd];
58 CELL *c = cell;
59 CELL *reclass_table = fcb->reclass.table;
60 CELL min = fcb->reclass.min;
61 CELL max = fcb->reclass.max;
62 int i;
63
64 for (i = 0; i < R__.rd_window.cols; i++) {
65 if (Rast_is_c_null_value(&c[i])) {
66 if (null_is_zero)
67 c[i] = 0;
68 continue;
69 }
70
71 if (c[i] < min || c[i] > max) {
72 if (null_is_zero)
73 c[i] = 0;
74 else
75 Rast_set_c_null_value(&c[i], 1);
76 continue;
77 }
78
79 c[i] = reclass_table[c[i] - min];
80
82 c[i] = 0;
83 }
84}
85
86static void read_data_fp_compressed(int fd, int row, unsigned char *data_buf,
87 int *nbytes)
88{
89 struct fileinfo *fcb = &R__.fileinfo[fd];
90 off_t t1 = fcb->row_ptr[row];
91 off_t t2 = fcb->row_ptr[row + 1];
92 size_t readamount = t2 - t1;
93 size_t bufsize = fcb->cellhd.cols * fcb->nbytes;
94 int ret;
95
96 if (lseek(fcb->data_fd, t1, SEEK_SET) == -1)
98 _("Error seeking fp raster data file for row %d of <%s>: %s"), row,
100
101 *nbytes = fcb->nbytes;
102
103 ret = G_read_compressed(fcb->data_fd, readamount, data_buf, bufsize,
104 fcb->cellhd.compressed);
105 if (ret <= 0)
106 G_fatal_error(_("Error uncompressing fp raster data for row %d of "
107 "<%s>: error code %d"),
108 row, fcb->name, ret);
109}
110
111static void rle_decompress(unsigned char *dst, const unsigned char *src,
112 int nbytes, int size)
113{
114 int pairs = size / (nbytes + 1);
115 int i;
116
117 for (i = 0; i < pairs; i++) {
118 int repeat = *src++;
119 int j;
120
121 for (j = 0; j < repeat; j++) {
122 memcpy(dst, src, nbytes);
123 dst += nbytes;
124 }
125
126 src += nbytes;
127 }
128}
129
130static void read_data_compressed(int fd, int row, unsigned char *data_buf,
131 int *nbytes)
132{
133 struct fileinfo *fcb = &R__.fileinfo[fd];
134 off_t t1 = fcb->row_ptr[row];
135 off_t t2 = fcb->row_ptr[row + 1];
136 ssize_t readamount = t2 - t1;
137 size_t bufsize;
138 unsigned char *cmp, *cmp2;
139 int n;
140
141 if (lseek(fcb->data_fd, t1, SEEK_SET) == -1)
143 _("Error seeking raster data file for row %d of <%s>: %s"), row,
145
146 cmp = G_malloc(readamount);
147
148 if (read(fcb->data_fd, cmp, readamount) != readamount) {
149 G_free(cmp);
150 G_fatal_error(_("Error reading raster data for row %d of <%s>: %s"),
151 row, fcb->name, strerror(errno));
152 }
153
154 /* save cmp for free below */
155 cmp2 = cmp;
156
157 /* Now decompress the row */
158 if (fcb->cellhd.compressed > 0) {
159 /* one byte is nbyte count */
160 n = *nbytes = *cmp++;
161 readamount--;
162 }
163 else
164 /* pre 3.0 compression */
165 n = *nbytes = fcb->nbytes;
166
167 bufsize = (size_t)n * fcb->cellhd.cols;
168 if (fcb->cellhd.compressed < 0 || (size_t)readamount < bufsize) {
169 if (fcb->cellhd.compressed == 1)
170 rle_decompress(data_buf, cmp, n, readamount);
171 else {
172 if ((n = G_expand(cmp, readamount, data_buf, bufsize,
173 fcb->cellhd.compressed)) < 0 ||
174 (unsigned int)n != bufsize) {
176 _("Error uncompressing raster data for row %d of <%s>"),
177 row, fcb->name);
178 }
179 }
180 }
181 else
183
184 G_free(cmp2);
185}
186
187static void read_data_uncompressed(int fd, int row, unsigned char *data_buf,
188 int *nbytes)
189{
190 struct fileinfo *fcb = &R__.fileinfo[fd];
191 ssize_t bufsize = fcb->cellhd.cols * fcb->nbytes;
192
193 *nbytes = fcb->nbytes;
194
195 if (lseek(fcb->data_fd, (off_t)row * bufsize, SEEK_SET) == -1)
196 G_fatal_error(_("Error reading raster data for row %d of <%s>"), row,
197 fcb->name);
198
199 if (read(fcb->data_fd, data_buf, bufsize) != bufsize)
200 G_fatal_error(_("Error reading raster data for row %d of <%s>"), row,
201 fcb->name);
202}
203
204static void read_data_gdal(int fd, int row, unsigned char *data_buf,
205 int *nbytes)
206{
207 struct fileinfo *fcb = &R__.fileinfo[fd];
208 unsigned char *buf;
209 CPLErr err;
210
211 *nbytes = fcb->nbytes;
212
213 if (fcb->gdal->vflip)
214 row = fcb->cellhd.rows - 1 - row;
215
216 buf = fcb->gdal->hflip ? G_malloc(fcb->cellhd.cols * fcb->cur_nbytes)
217 : data_buf;
218
219 err =
220 Rast_gdal_raster_IO(fcb->gdal->band, GF_Read, 0, row, fcb->cellhd.cols,
221 1, buf, fcb->cellhd.cols, 1, fcb->gdal->type, 0, 0);
222
223 if (fcb->gdal->hflip) {
224 int i;
225
226 for (i = 0; i < fcb->cellhd.cols; i++)
227 memcpy(data_buf + i * fcb->cur_nbytes,
228 buf + (fcb->cellhd.cols - 1 - i) * fcb->cur_nbytes,
229 fcb->cur_nbytes);
230 G_free(buf);
231 }
232
233 if (err != CE_None)
235 _("Error reading raster data via GDAL for row %d of <%s>"), row,
236 fcb->name);
237}
238
239static void read_data(int fd, int row, unsigned char *data_buf, int *nbytes)
240{
241 struct fileinfo *fcb = &R__.fileinfo[fd];
242
243 if (fcb->gdal) {
244 read_data_gdal(fd, row, data_buf, nbytes);
245 return;
246 }
247
248 if (!fcb->cellhd.compressed)
249 read_data_uncompressed(fd, row, data_buf, nbytes);
250 else if (fcb->map_type == CELL_TYPE)
251 read_data_compressed(fd, row, data_buf, nbytes);
252 else
253 read_data_fp_compressed(fd, row, data_buf, nbytes);
254}
255
256/* copy cell file data to user buffer translated by window column mapping */
257static void cell_values_int(int fd UNUSED, const unsigned char *data UNUSED,
258 const COLUMN_MAPPING *cmap, int nbytes UNUSED,
259 void *cell, int n)
260{
261 CELL *c = cell;
263 int big = (size_t)nbytes >= sizeof(CELL);
264 int i;
265
266 for (i = 0; i < n; i++) {
267 const unsigned char *d;
268 int neg;
269 CELL v;
270 int j;
271
272 if (!cmap[i]) {
273 c[i] = 0;
274 continue;
275 }
276
277 if (cmap[i] == cmapold) {
278 c[i] = c[i - 1];
279 continue;
280 }
281
282 d = data + (cmap[i] - 1) * nbytes;
283
284 if (big && (*d & 0x80)) {
285 neg = 1;
286 v = *d++ & 0x7f;
287 }
288 else {
289 neg = 0;
290 v = *d++;
291 }
292
293 for (j = 1; j < nbytes; j++)
294 v = (v << 8) + *d++;
295
296 c[i] = neg ? -v : v;
297
298 cmapold = cmap[i];
299 }
300}
301
302static void cell_values_float(int fd, const unsigned char *data UNUSED,
303 const COLUMN_MAPPING *cmap, int nbytes UNUSED,
304 void *cell, int n)
305{
306 struct fileinfo *fcb = &R__.fileinfo[fd];
307 const float *work_buf = (const float *)fcb->data;
308 FCELL *c = cell;
309 int i;
310
311 for (i = 0; i < n; i++) {
312 if (!cmap[i]) {
313 c[i] = 0;
314 continue;
315 }
316
317 G_xdr_get_float(&c[i], &work_buf[cmap[i] - 1]);
318 }
319}
320
321static void cell_values_double(int fd, const unsigned char *data UNUSED,
322 const COLUMN_MAPPING *cmap, int nbytes UNUSED,
323 void *cell, int n)
324{
325 struct fileinfo *fcb = &R__.fileinfo[fd];
326 const double *work_buf = (const double *)fcb->data;
327 DCELL *c = cell;
328 int i;
329
330 for (i = 0; i < n; i++) {
331 if (!cmap[i]) {
332 c[i] = 0;
333 continue;
334 }
335
336 G_xdr_get_double(&c[i], &work_buf[cmap[i] - 1]);
337 }
338}
339
340static void gdal_values_int(int fd, const unsigned char *data,
341 const COLUMN_MAPPING *cmap, int nbytes, void *cell,
342 int n)
343{
344 struct fileinfo *fcb = &R__.fileinfo[fd];
345 CELL *c = cell;
346 const unsigned char *d;
348 int i;
349
350 for (i = 0; i < n; i++) {
351 if (!cmap[i]) {
352 c[i] = 0;
353 continue;
354 }
355
356 if (cmap[i] == cmapold) {
357 c[i] = c[i - 1];
358 continue;
359 }
360
361 d = data + (cmap[i] - 1) * nbytes;
362
363 switch (fcb->gdal->type) {
364 case GDT_Byte:
365 c[i] = *(GByte *)d;
366 break;
367 case GDT_Int8:
368 c[i] = *(int8_t *)d;
369 break;
370 case GDT_Int16:
371 c[i] = *(GInt16 *)d;
372 break;
373 case GDT_UInt16:
374 c[i] = *(GUInt16 *)d;
375 break;
376 case GDT_Int32:
377 c[i] = *(GInt32 *)d;
378 break;
379 case GDT_UInt32:
380 c[i] = *(GUInt32 *)d;
381 break;
382 default:
383 /* shouldn't happen */
384 Rast_set_c_null_value(&c[i], 1);
385 break;
386 }
387
388 cmapold = cmap[i];
389 }
390}
391
392static void gdal_values_float(int fd UNUSED, const unsigned char *data,
393 const COLUMN_MAPPING *cmap, int nbytes UNUSED,
394 void *cell, int n)
395{
397 const float *d = (const float *)data;
398 FCELL *c = cell;
399 int i;
400
401 for (i = 0; i < n; i++) {
402 if (!cmap[i]) {
403 c[i] = 0;
404 continue;
405 }
406
407 if (cmap[i] == cmapold) {
408 c[i] = c[i - 1];
409 continue;
410 }
411
412 c[i] = d[cmap[i] - 1];
413
414 cmapold = cmap[i];
415 }
416}
417
418static void gdal_values_double(int fd UNUSED, const unsigned char *data,
419 const COLUMN_MAPPING *cmap, int nbytes UNUSED,
420 void *cell, int n)
421{
423 const double *d = (const double *)data;
424 DCELL *c = cell;
425 int i;
426
427 for (i = 0; i < n; i++) {
428 if (!cmap[i]) {
429 c[i] = 0;
430 continue;
431 }
432
433 if (cmap[i] == cmapold) {
434 c[i] = c[i - 1];
435 continue;
436 }
437
438 c[i] = d[cmap[i] - 1];
439
440 cmapold = cmap[i];
441 }
442}
443
444/* transfer_to_cell_XY takes bytes from fcb->data, converts these bytes with
445 the appropriate procedure (e.g. XDR or byte reordering) into type X
446 values which are put into array work_buf.
447 finally the values in work_buf are converted into
448 type Y and put into 'cell'.
449 if type X == type Y the intermediate step of storing the values in
450 work_buf might be omitted. check the appropriate function for XY to
451 determine the procedure of conversion.
452 */
453static void transfer_to_cell_XX(int fd, void *cell)
454{
455 static void (*cell_values_type[3])(
456 int, const unsigned char *, const COLUMN_MAPPING *, int, void *,
457 int) = {cell_values_int, cell_values_float, cell_values_double};
458 static void (*gdal_values_type[3])(
459 int, const unsigned char *, const COLUMN_MAPPING *, int, void *,
460 int) = {gdal_values_int, gdal_values_float, gdal_values_double};
461 struct fileinfo *fcb = &R__.fileinfo[fd];
462
463 if (fcb->gdal)
464 (gdal_values_type[fcb->map_type])(fd, fcb->data, fcb->col_map,
465 fcb->cur_nbytes, cell,
466 R__.rd_window.cols);
467 else
468 (cell_values_type[fcb->map_type])(fd, fcb->data, fcb->col_map,
469 fcb->cur_nbytes, cell,
470 R__.rd_window.cols);
471}
472
473static void transfer_to_cell_fi(int fd, void *cell)
474{
475 struct fileinfo *fcb = &R__.fileinfo[fd];
476 FCELL *work_buf = G_malloc(R__.rd_window.cols * sizeof(FCELL));
477 int i;
478
479 transfer_to_cell_XX(fd, work_buf);
480
481 for (i = 0; i < R__.rd_window.cols; i++)
482 ((CELL *)cell)[i] =
483 (fcb->col_map[i] == 0)
484 ? 0
486
488}
489
490static void transfer_to_cell_di(int fd, void *cell)
491{
492 struct fileinfo *fcb = &R__.fileinfo[fd];
493 DCELL *work_buf = G_malloc(R__.rd_window.cols * sizeof(DCELL));
494 int i;
495
496 transfer_to_cell_XX(fd, work_buf);
497
498 for (i = 0; i < R__.rd_window.cols; i++)
499 ((CELL *)cell)[i] =
500 (fcb->col_map[i] == 0)
501 ? 0
503
505}
506
507static void transfer_to_cell_if(int fd, void *cell)
508{
509 CELL *work_buf = G_malloc(R__.rd_window.cols * sizeof(CELL));
510 int i;
511
512 transfer_to_cell_XX(fd, work_buf);
513
514 for (i = 0; i < R__.rd_window.cols; i++)
515 ((FCELL *)cell)[i] = work_buf[i];
516
518}
519
520static void transfer_to_cell_df(int fd, void *cell)
521{
522 DCELL *work_buf = G_malloc(R__.rd_window.cols * sizeof(DCELL));
523 int i;
524
525 transfer_to_cell_XX(fd, work_buf);
526
527 for (i = 0; i < R__.rd_window.cols; i++)
528 ((FCELL *)cell)[i] = work_buf[i];
529
531}
532
533static void transfer_to_cell_id(int fd, void *cell)
534{
535 CELL *work_buf = G_malloc(R__.rd_window.cols * sizeof(CELL));
536 int i;
537
538 transfer_to_cell_XX(fd, work_buf);
539
540 for (i = 0; i < R__.rd_window.cols; i++)
541 ((DCELL *)cell)[i] = work_buf[i];
542
544}
545
546static void transfer_to_cell_fd(int fd, void *cell)
547{
548 FCELL *work_buf = G_malloc(R__.rd_window.cols * sizeof(FCELL));
549 int i;
550
551 transfer_to_cell_XX(fd, work_buf);
552
553 for (i = 0; i < R__.rd_window.cols; i++)
554 ((DCELL *)cell)[i] = work_buf[i];
555
557}
558
559/*
560 * works for all map types and doesn't consider
561 * null row corresponding to the requested row
562 */
563static int get_map_row_nomask(int fd, void *rast, int row,
564 RASTER_MAP_TYPE data_type)
565{
566 static void (*transfer_to_cell_FtypeOtype[3][3])(int, void *) = {
567 {transfer_to_cell_XX, transfer_to_cell_if, transfer_to_cell_id},
568 {transfer_to_cell_fi, transfer_to_cell_XX, transfer_to_cell_fd},
569 {transfer_to_cell_di, transfer_to_cell_df, transfer_to_cell_XX}};
570 struct fileinfo *fcb = &R__.fileinfo[fd];
571 int r;
572 int row_status;
573
574 /* is this the best place to read a vrt row, or
575 * call Rast_get_vrt_row() earlier ? */
576 if (fcb->vrt)
577 return Rast_get_vrt_row(fd, rast, row, data_type);
578
579 row_status = compute_window_row(fd, row, &r);
580
581 if (!row_status) {
582 fcb->cur_row = -1;
583 Rast_zero_input_buf(rast, data_type);
584 return 0;
585 }
586
587 /* read cell file row if not in memory */
588 if (r != fcb->cur_row) {
589 fcb->cur_row = r;
590 read_data(fd, fcb->cur_row, fcb->data, &fcb->cur_nbytes);
591 }
592
593 (transfer_to_cell_FtypeOtype[fcb->map_type][data_type])(fd, rast);
594
595 return 1;
596}
597
598static void get_map_row_no_reclass(int fd, void *rast, int row,
599 RASTER_MAP_TYPE data_type, int null_is_zero,
600 int with_mask)
601{
602 get_map_row_nomask(fd, rast, row, data_type);
603 embed_nulls(fd, rast, row, data_type, null_is_zero, with_mask);
604}
605
606static void get_map_row(int fd, void *rast, int row, RASTER_MAP_TYPE data_type,
607 int null_is_zero, int with_mask)
608{
609 struct fileinfo *fcb = &R__.fileinfo[fd];
610 int size = Rast_cell_size(data_type);
611 CELL *temp_buf = NULL;
612 void *buf;
613 int type;
614 int i;
615
616 if (fcb->reclass_flag && data_type != CELL_TYPE) {
617 temp_buf = G_malloc(R__.rd_window.cols * sizeof(CELL));
618 buf = temp_buf;
619 type = CELL_TYPE;
620 }
621 else {
622 buf = rast;
623 type = data_type;
624 }
625
626 get_map_row_no_reclass(fd, buf, row, type, null_is_zero, with_mask);
627
628 if (!fcb->reclass_flag)
629 return;
630
631 /* if the map is reclass table, get and
632 reclass CELL row and copy results to needed type */
633
634 do_reclass_int(fd, buf, null_is_zero);
635
636 if (data_type == CELL_TYPE)
637 return;
638
639 for (i = 0; i < R__.rd_window.cols; i++) {
640 Rast_set_c_value(rast, temp_buf[i], data_type);
641 rast = G_incr_void_ptr(rast, size);
642 }
643
644 if (fcb->reclass_flag && data_type != CELL_TYPE) {
646 }
647}
648
649/*!
650 * \brief Read raster row without masking
651 *
652 * This routine reads the specified <em>row</em> from the raster map
653 * open on file descriptor <em>fd</em> into the <em>buf</em> buffer
654 * like Rast_get_c_row() does. The difference is that masking is
655 * suppressed. If the user has a mask set, Rast_get_c_row() will apply
656 * the mask but Rast_get_c_row_nomask() will ignore it. This routine
657 * prints a diagnostic message and returns -1 if there is an error
658 * reading the raster map. Otherwise a nonnegative value is returned.
659 *
660 * <b>Note.</b> Ignoring the mask is not generally acceptable. Users
661 * expect the mask to be applied. However, in some cases ignoring the
662 * mask is justified. For example, the GRASS modules
663 * <i>r.describe</i>, which reads the raster map directly to report
664 * all data values in a raster map, and <i>r.slope.aspect</i>, which
665 * produces slope and aspect from elevation, ignore both the mask and
666 * the region. However, the number of GRASS modules which do this
667 * should be minimal. See Mask for more information about the mask.
668 *
669 * \param fd file descriptor for the opened raster map
670 * \param buf buffer for the row to be placed into
671 * \param row data row desired
672 * \param data_type data type
673 *
674 * \return void
675 */
676void Rast_get_row_nomask(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
677{
678 get_map_row(fd, buf, row, data_type, 0, 0);
679}
680
681/*!
682 * \brief Read raster row without masking (CELL type)
683 *
684 * Same as Rast_get_c_row() except no masking occurs.
685 *
686 * \param fd file descriptor for the opened raster map
687 * \param buf buffer for the row to be placed into
688 * \param row data row desired
689 *
690 * \return void
691 */
692void Rast_get_c_row_nomask(int fd, CELL *buf, int row)
693{
694 Rast_get_row_nomask(fd, buf, row, CELL_TYPE);
695}
696
697/*!
698 * \brief Read raster row without masking (FCELL type)
699 *
700 * Same as Rast_get_f_row() except no masking occurs.
701 *
702 * \param fd file descriptor for the opened raster map
703 * \param buf buffer for the row to be placed into
704 * \param row data row desired
705 *
706 * \return void
707 */
708void Rast_get_f_row_nomask(int fd, FCELL *buf, int row)
709{
710 Rast_get_row_nomask(fd, buf, row, FCELL_TYPE);
711}
712
713/*!
714 * \brief Read raster row without masking (DCELL type)
715 *
716 * Same as Rast_get_d_row() except no masking occurs.
717 *
718 * \param fd file descriptor for the opened raster map
719 * \param buf buffer for the row to be placed into
720 * \param row data row desired
721 *
722 * \return void
723 */
724void Rast_get_d_row_nomask(int fd, DCELL *buf, int row)
725{
726 Rast_get_row_nomask(fd, buf, row, DCELL_TYPE);
727}
728
729/*!
730 * \brief Get raster row
731 *
732 * If <em>data_type</em> is
733 * - CELL_TYPE, calls Rast_get_c_row()
734 * - FCELL_TYPE, calls Rast_get_f_row()
735 * - DCELL_TYPE, calls Rast_get_d_row()
736 *
737 * Reads appropriate information into the buffer <em>buf</em> associated
738 * with the requested row <em>row</em>. <em>buf</em> is associated with the
739 * current window.
740 *
741 * Note, that the type of the data in <em>buf</em> (say X) is independent of
742 * the type of the data in the file described by <em>fd</em> (say Y).
743 *
744 * - Step 1: Read appropriate raw map data into a intermediate buffer.
745 * - Step 2: Convert the data into a CPU readable format, and subsequently
746 * resample the data. the data is stored in a second intermediate
747 * buffer (the type of the data in this buffer is Y).
748 * - Step 3: Convert this type Y data into type X data and store it in
749 * buffer "buf". Conversion is performed in functions
750 * "transfer_to_cell_XY". (For details of the conversion between
751 * two particular types check the functions).
752 * - Step 4: read or simmulate null value row and zero out cells
753 * corresponding to null value cells. The masked out cells are set to null when
754 * the mask exists. (the mask is taken care of by null values (if the null file
755 * doesn't exist for this map, then the null row is simulated by assuming that
756 * all zero are nulls *** in case of Rast_get_row() and assuming that all data
757 * is valid in case of G_get_f/d_raster_row(). In case of deprecated function
758 * Rast_get_c_row() all nulls are converted to zeros (so there are
759 * no embedded nulls at all). Also all masked out cells become zeros.
760 *
761 * \param fd file descriptor for the opened raster map
762 * \param buf buffer for the row to be placed into
763 * \param row data row desired
764 * \param data_type data type
765 *
766 * \return void
767 */
768void Rast_get_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
769{
770 get_map_row(fd, buf, row, data_type, 0, 1);
771}
772
773/*!
774 * \brief Get raster row (CELL type)
775 *
776 * Reads a row of raster data and leaves the NULL values intact. (As
777 * opposed to the deprecated function Rast_get_c_row() which
778 * converts NULL values to zero.)
779 *
780 * <b>NOTE.</b> When the raster map is old and null file doesn't
781 * exist, it is assumed that all 0-cells are no-data. When map is
782 * floating point, uses quant rules set explicitly by
783 * Rast_set_quant_rules() or stored in map's quant file to convert floats
784 * to integers.
785 *
786 * \param fd file descriptor for the opened raster map
787 * \param buf buffer for the row to be placed into
788 * \param row data row desired
789 *
790 * \return void
791 */
792void Rast_get_c_row(int fd, CELL *buf, int row)
793{
794 Rast_get_row(fd, buf, row, CELL_TYPE);
795}
796
797/*!
798 * \brief Get raster row (FCELL type)
799 *
800 * Read a row from the raster map open on <em>fd</em> into the
801 * <tt>float</tt> array <em>fcell</em> performing type conversions as
802 * necessary based on the actual storage type of the map. Masking,
803 * resampling into the current region. NULL-values are always
804 * embedded in <tt>fcell</tt> (<em>never converted to a value</em>).
805 *
806 * \param fd file descriptor for the opened raster map
807 * \param buf buffer for the row to be placed into
808 * \param row data row desired
809 *
810 * \return void
811 */
812void Rast_get_f_row(int fd, FCELL *buf, int row)
813{
814 Rast_get_row(fd, buf, row, FCELL_TYPE);
815}
816
817/*!
818 * \brief Get raster row (DCELL type)
819 *
820 * Same as Rast_get_f_row() except that the array <em>dcell</em>
821 * is <tt>double</tt>.
822 *
823 * \param fd file descriptor for the opened raster map
824 * \param buf buffer for the row to be placed into
825 * \param row data row desired
826 *
827 * \return void
828 */
829void Rast_get_d_row(int fd, DCELL *buf, int row)
830{
831 Rast_get_row(fd, buf, row, DCELL_TYPE);
832}
833
834static int read_null_bits_compressed(int null_fd, unsigned char *flags, int row,
835 size_t size, int fd)
836{
837 struct fileinfo *fcb = &R__.fileinfo[fd];
838 off_t t1 = fcb->null_row_ptr[row];
839 off_t t2 = fcb->null_row_ptr[row + 1];
840 size_t readamount = t2 - t1;
841 unsigned char *compressed_buf;
842 int res;
843
844 if (lseek(null_fd, t1, SEEK_SET) == -1)
846 _("Error seeking compressed null data for row %d of <%s>"), row,
847 fcb->name);
848
849 if (readamount == size) {
850 if ((res = read(null_fd, flags, size)) < 0 ||
851 (unsigned int)res != size) {
853 _("Error reading compressed null data for row %d of <%s>"), row,
854 fcb->name);
855 }
856 return 1;
857 }
858
860
861 if ((res = read(null_fd, compressed_buf, readamount)) < 0 ||
862 (unsigned int)res != readamount) {
865 _("Error reading compressed null data for row %d of <%s>"), row,
866 fcb->name);
867 }
868
869 /* null bits file compressed with LZ4, see lib/gis/compress.h */
870 if (G_lz4_expand(compressed_buf, readamount, flags, size) < 1) {
871 G_fatal_error(_("Error uncompressing null data for row %d of <%s>"),
872 row, fcb->name);
873 }
874
876
877 return 1;
878}
879
880int Rast__read_null_bits(int fd, int row, unsigned char *flags)
881{
882 struct fileinfo *fcb = &R__.fileinfo[fd];
883 int null_fd = fcb->null_fd;
884 int cols = fcb->cellhd.cols;
885 off_t offset;
886 ssize_t size;
887 int R;
888
889 if (compute_window_row(fd, row, &R) <= 0) {
890 Rast__init_null_bits(flags, cols);
891 return 1;
892 }
893
894 if (null_fd < 0)
895 return 0;
896
897 size = Rast__null_bitstream_size(cols);
898
899 if (fcb->null_row_ptr)
900 return read_null_bits_compressed(null_fd, flags, R, size, fd);
901
902 offset = (off_t)size * R;
903
904 if (lseek(null_fd, offset, SEEK_SET) == -1)
905 G_fatal_error(_("Error seeking null row %d for <%s>"), R, fcb->name);
906
907 if (read(null_fd, flags, size) != size)
908 G_fatal_error(_("Error reading null row %d for <%s>"), R, fcb->name);
909
910 return 1;
911}
912
913#define check_null_bit(flags, bit_num) \
914 ((flags)[(bit_num) >> 3] & ((unsigned char)0x80 >> ((bit_num) & 7)) ? 1 : 0)
915
916static void get_null_value_row_nomask(int fd, char *flags, int row)
917{
918 struct fileinfo *fcb = &R__.fileinfo[fd];
919 int j;
920
921 if (row > R__.rd_window.rows || row < 0) {
922 G_warning(_("Reading raster map <%s@%s> request for row %d is outside "
923 "region"),
924 fcb->name, fcb->mapset, row);
925 for (j = 0; j < R__.rd_window.cols; j++)
926 flags[j] = 1;
927 return;
928 }
929 if (fcb->vrt) {
930 /* vrt: already done when reading the real maps, no extra NULL values */
931 for (j = 0; j < R__.rd_window.cols; j++)
932 flags[j] = 0;
933 return;
934 }
935
936 if (row != fcb->null_cur_row) {
937 if (!Rast__read_null_bits(fd, row, fcb->null_bits)) {
938 fcb->null_cur_row = -1;
939 if (fcb->map_type == CELL_TYPE) {
940 /* If can't read null row, assume that all map 0's are nulls */
941 CELL *mask_buf = G_malloc(R__.rd_window.cols * sizeof(CELL));
942
943 get_map_row_nomask(fd, mask_buf, row, CELL_TYPE);
944 for (j = 0; j < R__.rd_window.cols; j++)
945 flags[j] = (mask_buf[j] == 0);
946
948 }
949 else { /* fp map */
950 /* if can't read null row, assume that all data is valid */
951 G_zero(flags, sizeof(char) * R__.rd_window.cols);
952 /* the flags row is ready now */
953 }
954
955 return;
956 } /*if no null file */
957 else
958 fcb->null_cur_row = row;
959 }
960
961 /* copy null row to flags row translated by window column mapping */
962 for (j = 0; j < R__.rd_window.cols; j++) {
963 if (!fcb->col_map[j])
964 flags[j] = 1;
965 else
966 flags[j] = check_null_bit(fcb->null_bits, fcb->col_map[j] - 1);
967 }
968}
969
970/*--------------------------------------------------------------------------*/
971
972static void get_null_value_row_gdal(int fd, char *flags, int row)
973{
974 struct fileinfo *fcb = &R__.fileinfo[fd];
976 int i;
977
978 if (get_map_row_nomask(fd, tmp_buf, row, DCELL_TYPE) <= 0) {
979 memset(flags, 1, R__.rd_window.cols);
981 return;
982 }
983
984 for (i = 0; i < R__.rd_window.cols; i++)
985 /* note: using == won't work if the null value is NaN */
986 flags[i] = !fcb->col_map[i] || tmp_buf[i] == fcb->gdal->null_val ||
987 tmp_buf[i] != tmp_buf[i];
988
990}
991
992/*--------------------------------------------------------------------------*/
993
994/*--------------------------------------------------------------------------*/
995
996static void embed_mask(char *flags, int row)
997{
998 CELL *mask_buf = G_malloc(R__.rd_window.cols * sizeof(CELL));
999 int i;
1000
1001 if (R__.auto_mask <= 0) {
1003 return;
1004 }
1005
1006 if (get_map_row_nomask(R__.mask_fd, mask_buf, row, CELL_TYPE) < 0) {
1008 return;
1009 }
1010
1011 if (R__.fileinfo[R__.mask_fd].reclass_flag) {
1012 embed_nulls(R__.mask_fd, mask_buf, row, CELL_TYPE, 0, 0);
1013 do_reclass_int(R__.mask_fd, mask_buf, 1);
1014 }
1015
1016 for (i = 0; i < R__.rd_window.cols; i++)
1017 if (mask_buf[i] == 0 || Rast_is_c_null_value(&mask_buf[i]))
1018 flags[i] = 1;
1019
1021}
1022
1023static void get_null_value_row(int fd, char *flags, int row, int with_mask)
1024{
1025 struct fileinfo *fcb = &R__.fileinfo[fd];
1026
1027 if (fcb->gdal)
1028 get_null_value_row_gdal(fd, flags, row);
1029 else
1030 get_null_value_row_nomask(fd, flags, row);
1031
1032 if (with_mask)
1033 embed_mask(flags, row);
1034}
1035
1036static void embed_nulls(int fd, void *buf, int row, RASTER_MAP_TYPE map_type,
1037 int null_is_zero, int with_mask)
1038{
1039 struct fileinfo *fcb = &R__.fileinfo[fd];
1040 size_t size = Rast_cell_size(map_type);
1041 char *null_buf;
1042 int i;
1043
1044 /* this is because without null file the nulls can be only due to 0's
1045 in data row or mask */
1046 if (null_is_zero && !fcb->null_file_exists &&
1047 (R__.auto_mask <= 0 || !with_mask))
1048 return;
1049
1051
1052 get_null_value_row(fd, null_buf, row, with_mask);
1053
1054 for (i = 0; i < R__.rd_window.cols; i++) {
1055 /* also check for nulls which might be already embedded by quant
1056 rules in case of fp map. */
1057 if (null_buf[i] || Rast_is_null_value(buf, map_type)) {
1058 /* G__set_[f/d]_null_value() sets it to 0 is the embedded mode
1059 is not set and calls G_set_[f/d]_null_value() otherwise */
1061 }
1062 buf = G_incr_void_ptr(buf, size);
1063 }
1064
1066}
1067
1068/*!
1069 \brief Read or simulate null value row
1070
1071 Read or simulate null value row and set the cells corresponding
1072 to null value to 1. The masked out cells are set to null when the
1073 mask exists. (the mask is taken care of by null values
1074 (if the null file doesn't exist for this map, then the null row
1075 is simulated by assuming that all zeros in raster map are nulls.
1076 Also all masked out cells become nulls.
1077
1078 \param fd file descriptor for the opened map
1079 \param buf buffer for the row to be placed into
1080 \param flags
1081 \param row data row desired
1082
1083 \return void
1084 */
1085void Rast_get_null_value_row(int fd, char *flags, int row)
1086{
1087 struct fileinfo *fcb = &R__.fileinfo[fd];
1088
1089 if (!fcb->reclass_flag)
1090 get_null_value_row(fd, flags, row, 1);
1091 else {
1092 CELL *buf = G_malloc(R__.rd_window.cols * sizeof(CELL));
1093 int i;
1094
1095 Rast_get_c_row(fd, buf, row);
1096 for (i = 0; i < R__.rd_window.cols; i++)
1097 flags[i] = Rast_is_c_null_value(&buf[i]) ? 1 : 0;
1098
1099 G_free(buf);
1100 }
1101}
#define NULL
Definition ccmath.h:32
AMI_err name(char **stream_name)
Definition ami_stream.h:426
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
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_expand(unsigned char *, int, unsigned char *, int, int)
Definition compress.c:233
void G_xdr_get_float(float *, const void *)
Definition gis/xdr.c:79
#define G_malloc(n)
Definition defs/gis.h:139
int G_lz4_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprlz4.c:146
int G_read_compressed(int, int, unsigned char *, int, int)
Definition compress.c:244
void G_xdr_get_double(double *, const void *)
Definition gis/xdr.c:89
#define G_incr_void_ptr(ptr, size)
Definition defs/gis.h:81
int Rast_is_null_value(const void *, RASTER_MAP_TYPE)
To check if a raster value is set to NULL.
Definition null_val.c:176
int Rast__null_bitstream_size(int)
Determines null bitstream size.
Definition alloc_cell.c:146
CELL Rast_quant_get_cell_value(struct Quant *, DCELL)
Returns a CELL category for the floating-point value based on the quantization rules in q....
Definition quant.c:592
int Rast_get_vrt_row(int, void *, int, RASTER_MAP_TYPE)
Definition vrt.c:171
void Rast_zero_input_buf(void *, RASTER_MAP_TYPE)
Definition zero_cell.c:33
void Rast_set_c_null_value(CELL *, int)
To set a number of CELL raster values to NULL.
Definition null_val.c:124
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition alloc_cell.c:37
void Rast_set_c_value(void *, CELL, RASTER_MAP_TYPE)
Places a CELL raster value.
void Rast__set_null_value(void *, int, int, RASTER_MAP_TYPE)
To set one or more raster values to null.
Definition null_val.c:80
void Rast__init_null_bits(unsigned char *, int)
?
Definition null_val.c:490
#define Rast_is_c_null_value(cellVal)
DCELL * Rast_allocate_d_input_buf(void)
Definition alloc_cell.c:170
#define min(x, y)
Definition draw2.c:29
#define max(x, y)
Definition draw2.c:30
CPLErr Rast_gdal_raster_IO(GDALRasterBandH band, GDALRWFlag rw_flag, int x_off, int y_off, int x_size, int y_size, void *buffer, int buf_x_size, int buf_y_size, GDALDataType buf_type, int pixel_size, int line_size)
Input/output function for GDAL links.
Definition gdal.c:427
float FCELL
Definition gis.h:636
double DCELL
Definition gis.h:635
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition gis.h:46
int CELL
Definition gis.h:634
#define _(str)
Definition glocale.h:10
double r
Definition r_raster.c:39
void Rast_get_c_row_nomask(int fd, CELL *buf, int row)
Read raster row without masking (CELL type)
#define check_null_bit(flags, bit_num)
void Rast_get_null_value_row(int fd, char *flags, int row)
Read or simulate null value row.
void Rast_get_f_row_nomask(int fd, FCELL *buf, int row)
Read raster row without masking (FCELL type)
void Rast_get_row_nomask(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
Read raster row without masking.
void Rast_get_d_row_nomask(int fd, DCELL *buf, int row)
Read raster row without masking (DCELL type)
void Rast_get_d_row(int fd, DCELL *buf, int row)
Get raster row (DCELL type)
void Rast_get_c_row(int fd, CELL *buf, int row)
Get raster row (CELL type)
void Rast_get_f_row(int fd, FCELL *buf, int row)
Get raster row (FCELL type)
void Rast_get_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
Get raster row.
int Rast__read_null_bits(int fd, int row, unsigned char *flags)
#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
Definition R.h:82
struct fileinfo * fileinfo
Definition R.h:96
int auto_mask
Definition R.h:85
int mask_fd
Definition R.h:84
struct Cell_head rd_window
Definition R.h:92
Definition R.h:48
struct Quant quant
Definition R.h:74
RASTER_MAP_TYPE map_type
Definition R.h:67
int null_fd
Definition R.h:64
unsigned char * data
Definition R.h:63
int nbytes
Definition R.h:66
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
#define read
Definition unistd.h:5