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