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