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