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