1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 |
- /*!
- \file get_row.c
- \brief GIS library - get raster row
- (C) 2003-2008 by the GRASS Development Team
- This program is free software under the
- GNU General Public License (>=v2).
- Read the file COPYING that comes with GRASS
- for details.
- \author Original author CERL
- */
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <rpc/types.h> /* need this for sgi */
- #include <rpc/xdr.h>
- #include <grass/config.h>
- #include <grass/glocale.h>
- #include "G.h"
- /*--------------------------------------------------------------------------*/
- #define NULL_FILE "null"
- /*--------------------------------------------------------------------------*/
- static int embed_nulls(int, void *, int, RASTER_MAP_TYPE, int, int);
- /*--------------------------------------------------------------------------*/
- static int compute_window_row(int fd, int row, int *cellRow)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- double f;
- int r;
- /* check for row in window */
- if (row < 0 || row >= G__.window.rows) {
- G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"),
- fcb->name, fcb->mapset, row);
- return -1;
- }
- /* convert window row to cell file row */
- f = row * fcb->C1 + fcb->C2;
- r = (int)f;
- if (f < r) /* adjust for rounding up of negatives */
- r--;
- if (r < 0 || r >= fcb->cellhd.rows)
- return 0;
- *cellRow = r;
- return 1;
- }
- /*--------------------------------------------------------------------------*/
- static void do_reclass_int(int fd, void *cell, int null_is_zero)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- CELL *c = cell;
- CELL *reclass_table = fcb->reclass.table;
- CELL min = fcb->reclass.min;
- CELL max = fcb->reclass.max;
- int i;
- for (i = 0; i < G__.window.cols; i++) {
- if (G_is_c_null_value(&c[i])) {
- if (null_is_zero)
- c[i] = 0;
- continue;
- }
- if (c[i] < min || c[i] > max) {
- if (null_is_zero)
- c[i] = 0;
- else
- G_set_c_null_value(&c[i], 1);
- continue;
- }
- c[i] = reclass_table[c[i] - min];
- if (null_is_zero && G_is_c_null_value(&c[i]))
- c[i] = 0;
- }
- }
- /*--------------------------------------------------------------------------*/
- static int read_data_fp_compressed(int fd, int row, unsigned char *data_buf,
- int *nbytes)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- off_t t1 = fcb->row_ptr[row];
- off_t t2 = fcb->row_ptr[row + 1];
- size_t readamount = t2 - t1;
- size_t bufsize = fcb->cellhd.cols * fcb->nbytes;
- if (lseek(fd, t1, SEEK_SET) < 0)
- return -1;
- *nbytes = fcb->nbytes;
- if ((size_t) G_zlib_read(fd, readamount, data_buf, bufsize) != bufsize)
- return -1;
- return 0;
- }
- /*--------------------------------------------------------------------------*/
- static void rle_decompress(unsigned char *dst, const unsigned char *src,
- int nbytes, int size)
- {
- int pairs = size / (nbytes + 1);
- int i;
- for (i = 0; i < pairs; i++) {
- int repeat = *src++;
- int j;
- for (j = 0; j < repeat; j++) {
- memcpy(dst, src, nbytes);
- dst += nbytes;
- }
- src += nbytes;
- }
- }
- static int read_data_compressed(int fd, int row, unsigned char *data_buf,
- int *nbytes)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- off_t t1 = fcb->row_ptr[row];
- off_t t2 = fcb->row_ptr[row + 1];
- ssize_t readamount = t2 - t1;
- unsigned char *cmp = G__.compressed_buf;
- int n;
- if (lseek(fd, t1, SEEK_SET) < 0)
- return -1;
- if (read(fd, cmp, readamount) != readamount)
- return -1;
- /* Now decompress the row */
- if (fcb->cellhd.compressed > 0) {
- /* one byte is nbyte count */
- n = *nbytes = *cmp++;
- readamount--;
- }
- else
- /* pre 3.0 compression */
- n = *nbytes = fcb->nbytes;
- if (fcb->cellhd.compressed < 0 || readamount < n * fcb->cellhd.cols) {
- if (fcb->cellhd.compressed == 2)
- G_zlib_expand(cmp, readamount, data_buf, n * fcb->cellhd.cols);
- else
- rle_decompress(data_buf, cmp, n, readamount);
- }
- else
- memcpy(data_buf, cmp, readamount);
- return 0;
- }
- /*--------------------------------------------------------------------------*/
- static int read_data_uncompressed(int fd, int row, unsigned char *data_buf,
- int *nbytes)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- ssize_t bufsize = fcb->cellhd.cols * fcb->nbytes;
- *nbytes = fcb->nbytes;
- if (lseek(fd, (off_t) row * bufsize, SEEK_SET) == -1)
- return -1;
- if (read(fd, data_buf, bufsize) != bufsize)
- return -1;
- return 0;
- }
- /*--------------------------------------------------------------------------*/
- /* Actually read a row of data in */
- static int read_data(int fd, int row, unsigned char *data_buf, int *nbytes)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- if (!fcb->cellhd.compressed)
- return read_data_uncompressed(fd, row, data_buf, nbytes);
- /* map is in compressed form */
- if (fcb->map_type == CELL_TYPE)
- return read_data_compressed(fd, row, data_buf, nbytes);
- else
- return read_data_fp_compressed(fd, row, data_buf, nbytes);
- }
- /*--------------------------------------------------------------------------*/
- /* copy cell file data to user buffer translated by window column mapping */
- static void cell_values_int(int fd, const unsigned char *data,
- const COLUMN_MAPPING * cmap, int nbytes,
- void *cell, int n)
- {
- CELL *c = cell;
- COLUMN_MAPPING cmapold = 0;
- int big = (size_t) nbytes >= sizeof(CELL);
- int i;
- for (i = 0; i < n; i++) {
- const unsigned char *d;
- int neg;
- CELL v;
- int j;
- if (!cmap[i]) {
- c[i] = 0;
- continue;
- }
- if (cmap[i] == cmapold) {
- c[i] = c[i - 1];
- continue;
- }
- d = data + (cmap[i] - 1) * nbytes;
- if (big && (*d & 0x80)) {
- neg = 1;
- v = *d++ & 0x7f;
- }
- else {
- neg = 0;
- v = *d++;
- }
- for (j = 1; j < nbytes; j++)
- v = (v << 8) + *d++;
- c[i] = neg ? -v : v;
- cmapold = cmap[i];
- }
- }
- /*--------------------------------------------------------------------------*/
- static void cell_values_float(int fd, const unsigned char *data,
- const COLUMN_MAPPING * cmap, int nbytes,
- void *cell, int n)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- FCELL *c = cell;
- COLUMN_MAPPING cmapold = 0;
- XDR *xdrs = &fcb->xdrstream;
- int i;
- /* xdr stream is initialized to read from */
- /* fcb->data in 'opencell.c' */
- xdr_setpos(xdrs, 0);
- for (i = 0; i < n; i++) {
- if (!cmap[i]) {
- c[i] = 0;
- continue;
- }
- if (cmap[i] == cmapold) {
- c[i] = c[i - 1];
- continue;
- }
- if (cmap[i] < cmapold) {
- xdr_setpos(xdrs, 0);
- cmapold = 0;
- }
- while (cmapold++ != cmap[i]) /* skip */
- if (!xdr_float(xdrs, &c[i]))
- G_fatal_error(_("cell_values_float: xdr_float failed for index %d"),
- i);
- cmapold--;
- }
- }
- /*--------------------------------------------------------------------------*/
- static void cell_values_double(int fd, const unsigned char *data,
- const COLUMN_MAPPING * cmap, int nbytes,
- void *cell, int n)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- DCELL *c = cell;
- COLUMN_MAPPING cmapold = 0;
- XDR *xdrs = &fcb->xdrstream;
- int i;
- /* xdr stream is initialized to read from */
- /* fcb->data in 'opencell.c' */
- xdr_setpos(xdrs, 0);
- for (i = 0; i < n; i++) {
- if (!cmap[i]) {
- c[i] = 0;
- continue;
- }
- if (cmap[i] == cmapold) {
- c[i] = c[i - 1];
- continue;
- }
- if (cmap[i] < cmapold) {
- xdr_setpos(xdrs, 0);
- cmapold = 0;
- }
- while (cmapold++ != cmap[i]) /* skip */
- if (!xdr_double(xdrs, &c[i]))
- G_fatal_error(_("cell_values_double: xdr_double failed for index %d"),
- i);
- cmapold--;
- }
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /* transfer_to_cell_XY takes bytes from fcb->data, converts these bytes with
- the appropriate procedure (e.g. XDR or byte reordering) into type X
- values which are put into array G__.work_buf.
- finally the values in G__.work_buf are converted into
- type Y and put into 'cell'.
- if type X == type Y the intermediate step of storing the values in
- G__.work_buf might be ommited. check the appropriate function for XY to
- determine the procedure of conversion.
- */
- /*--------------------------------------------------------------------------*/
- static void transfer_to_cell_XX(int fd, void *cell)
- {
- static void (*cell_values_type[3]) () = {
- cell_values_int, cell_values_float, cell_values_double};
- struct fileinfo *fcb = &G__.fileinfo[fd];
- (cell_values_type[fcb->map_type]) (fd, fcb->data, fcb->col_map,
- fcb->cur_nbytes, cell,
- G__.window.cols);
- }
- /*--------------------------------------------------------------------------*/
- static void transfer_to_cell_fi(int fd, void *cell)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- int i;
- transfer_to_cell_XX(fd, G__.work_buf);
- for (i = 0; i < G__.window.cols; i++)
- ((CELL *) cell)[i] = (fcb->col_map[i] == 0)
- ? 0
- : G_quant_get_cell_value(&fcb->quant,
- ((FCELL *) G__.work_buf)[i]);
- }
- static void transfer_to_cell_di(int fd, void *cell)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- int i;
- transfer_to_cell_XX(fd, G__.work_buf);
- for (i = 0; i < G__.window.cols; i++)
- ((CELL *) cell)[i] = (fcb->col_map[i] == 0)
- ? 0
- : G_quant_get_cell_value(&fcb->quant,
- ((DCELL *) G__.work_buf)[i]);
- }
- /*--------------------------------------------------------------------------*/
- static void transfer_to_cell_if(int fd, void *cell)
- {
- int i;
- transfer_to_cell_XX(fd, G__.work_buf);
- for (i = 0; i < G__.window.cols; i++)
- ((FCELL *) cell)[i] = ((CELL *) G__.work_buf)[i];
- }
- static void transfer_to_cell_df(int fd, void *cell)
- {
- int i;
- transfer_to_cell_XX(fd, G__.work_buf);
- for (i = 0; i < G__.window.cols; i++)
- ((FCELL *) cell)[i] = ((DCELL *) G__.work_buf)[i];
- }
- /*--------------------------------------------------------------------------*/
- static void transfer_to_cell_id(int fd, void *cell)
- {
- int i;
- transfer_to_cell_XX(fd, G__.work_buf);
- for (i = 0; i < G__.window.cols; i++)
- ((DCELL *) cell)[i] = ((CELL *) G__.work_buf)[i];
- }
- static void transfer_to_cell_fd(int fd, void *cell)
- {
- int i;
- transfer_to_cell_XX(fd, G__.work_buf);
- for (i = 0; i < G__.window.cols; i++)
- ((DCELL *) cell)[i] = ((FCELL *) G__.work_buf)[i];
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*
- * works for all map types and doesn't consider
- * null row corresponding to the requested row
- */
- static int get_map_row_nomask(int fd, void *rast, int row,
- RASTER_MAP_TYPE data_type)
- {
- static void (*transfer_to_cell_FtypeOtype[3][3]) () = { {
- transfer_to_cell_XX, transfer_to_cell_if, transfer_to_cell_id}, {
- transfer_to_cell_fi, transfer_to_cell_XX, transfer_to_cell_fd}, {
- transfer_to_cell_di, transfer_to_cell_df, transfer_to_cell_XX}};
- struct fileinfo *fcb = &G__.fileinfo[fd];
- int r;
- int rowStatus;
- rowStatus = compute_window_row(fd, row, &r);
- if (rowStatus <= 0) {
- fcb->cur_row = -1;
- G_zero_raster_buf(rast, data_type);
- return rowStatus;
- }
- /* read cell file row if not in memory */
- if (r != fcb->cur_row) {
- fcb->cur_row = r;
- if (read_data(fd, fcb->cur_row, fcb->data, &fcb->cur_nbytes) < 0) {
- G_zero_raster_buf(rast, data_type);
- if (!fcb->io_error) {
- if (fcb->cellhd.compressed)
- G_warning(_("Error reading compressed map <%s@%s>, row %d"),
- fcb->name, fcb->mapset, r);
- else
- G_warning(_("Error reading map <%s@%s>, row %d"),
- fcb->name, fcb->mapset, r);
- fcb->io_error = 1;
- }
- return -1;
- }
- }
- (transfer_to_cell_FtypeOtype[fcb->map_type][data_type]) (fd, rast);
- return 1;
- }
- /*--------------------------------------------------------------------------*/
- static int get_map_row_no_reclass(int fd, void *rast, int row,
- RASTER_MAP_TYPE data_type, int null_is_zero,
- int with_mask)
- {
- int stat;
- stat = get_map_row_nomask(fd, rast, row, data_type);
- if (stat < 0)
- return stat;
- stat = embed_nulls(fd, rast, row, data_type, null_is_zero, with_mask);
- if (stat < 0)
- return stat;
- return 1;
- }
- /*--------------------------------------------------------------------------*/
- static int get_map_row(int fd, void *rast, int row, RASTER_MAP_TYPE data_type,
- int null_is_zero, int with_mask)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- int size = G_raster_size(data_type);
- void *buf;
- int type;
- int stat;
- int i;
- if (fcb->reclass_flag && data_type != CELL_TYPE) {
- buf = G__.temp_buf;
- type = CELL_TYPE;
- }
- else {
- buf = rast;
- type = data_type;
- }
- stat =
- get_map_row_no_reclass(fd, buf, row, type, null_is_zero, with_mask);
- if (stat < 0)
- return stat;
- if (!fcb->reclass_flag)
- return 1;
- /* if the map is reclass table, get and
- reclass CELL row and copy results to needed type */
- do_reclass_int(fd, buf, null_is_zero);
- if (data_type == CELL_TYPE)
- return 1;
- for (i = 0; i < G__.window.cols; i++) {
- G_set_raster_value_c(rast, G__.temp_buf[i], data_type);
- rast = G_incr_void_ptr(rast, size);
- }
- return 1;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*!
- * \brief Read raster row without masking (this routine is deprecated)
- *
- * This routine reads the specified <em>row</em> from the raster map
- * open on file descriptor <em>fd</em> into the <em>buf</em> buffer
- * like G_get_map_row() does. The difference is that masking is
- * suppressed. If the user has a mask set, G_get_map_row() will apply
- * the mask but G_get_map_row_nomask() will ignore it. This routine
- * prints a diagnostic message and returns -1 if there is an error
- * reading the raster map. Otherwise a nonnegative value is returned.
- *
- * <b>Note.</b> Ignoring the mask is not generally acceptable. Users
- * expect the mask to be applied. However, in some cases ignoring the
- * mask is justified. For example, the GRASS modules
- * <i>r.describe</i>, which reads the raster map directly to report
- * all data values in a raster map, and <i>r.slope.aspect</i>, which
- * produces slope and aspect from elevation, ignore both the mask and
- * the region. However, the number of GRASS modules which do this
- * should be minimal. See Mask for more information about the mask.
- *
- * <b>This routine is deprecated! Use G_get_raster_row_nomask()
- * instead.</b>
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_map_row_nomask(int fd, CELL * buf, int row)
- {
- return get_map_row(fd, buf, row, CELL_TYPE, 1, 0);
- }
- /*!
- * \brief Read raster row without masking
- *
- * Same as G_get_raster_row() except no masking occurs.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- * \param data_type data type
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_raster_row_nomask(int fd, void *buf, int row,
- RASTER_MAP_TYPE data_type)
- {
- return get_map_row(fd, buf, row, data_type, 0, 0);
- }
- /*!
- * \brief Read raster row without masking (CELL type)
- *
- * Same as G_get_c_raster_row() except no masking occurs.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- * \param data_type data type
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_c_raster_row_nomask(int fd, CELL * buf, int row)
- {
- return G_get_raster_row_nomask(fd, buf, row, CELL_TYPE);
- }
- /*!
- * \brief Read raster row without masking (FCELL type)
- *
- * Same as G_get_f_raster_row() except no masking occurs.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- * \param data_type data type
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_f_raster_row_nomask(int fd, FCELL * buf, int row)
- {
- return G_get_raster_row_nomask(fd, buf, row, FCELL_TYPE);
- }
- /*!
- * \brief Read raster row without masking (DCELL type)
- *
- * Same as G_get_d_raster_row() except no masking occurs.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- * \param data_type data type
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_d_raster_row_nomask(int fd, DCELL * buf, int row)
- {
- return G_get_raster_row_nomask(fd, buf, row, DCELL_TYPE);
- }
- /*--------------------------------------------------------------------------*/
- /*!
- * \brief Get raster row (this routine is deprecated!)
- *
- * If the map is floating-point, quantize the floating-point values to
- * integer using the quantization rules established for the map when
- * the map was opened for reading (this quantization is read from
- * cell_misc/name/f_quant file, but can be reset after opening raster
- * map by G_set_quant_rules()). NULL values are converted to zeros.
- *
- * <b>This routine is deprecated! Use G_get_raster_row() instead.</b>
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_map_row(int fd, CELL * buf, int row)
- {
- return get_map_row(fd, buf, row, CELL_TYPE, 1, 1);
- }
- /*!
- * \brief Get raster row
- *
- * If <em>data_type</em> is
- * - CELL_TYPE, calls G_get_c_raster_row()
- * - FCELL_TYPE, calls G_get_f_raster_row()
- * - DCELL_TYPE, calls G_get_d_raster_row()
- *
- * Reads appropriate information into the buffer <em>buf</em> associated
- * with the requested row <em>row</em>. <em>buf</em> is associated with the
- * current window.
- *
- * Note, that the type of the data in <em>buf</em> (say X) is independent of
- * the type of the data in the file described by <em>fd</em> (say Y).
- *
- * - Step 1: Read appropriate raw map data into a intermediate buffer.
- * - Step 2: Convert the data into a CPU readable format, and subsequently
- * resample the data. the data is stored in a second intermediate
- * buffer (the type of the data in this buffer is Y).
- * - Step 3: Convert this type Y data into type X data and store it in
- * buffer "buf". Conversion is performed in functions
- * "transfer_to_cell_XY". (For details of the conversion between
- * two particular types check the functions).
- * - Step 4: read or simmulate null value row and zero out cells corresponding
- * to null value cells. The masked out cells are set to null when the
- * mask exists. (the MASK is taken care of by null values
- * (if the null file doesn't exist for this map, then the null row
- * is simulated by assuming that all zero are nulls *** in case
- * of G_get_raster_row() and assuming that all data is valid
- * in case of G_get_f/d_raster_row(). In case of deprecated function
- * G_get_map_row() all nulls are converted to zeros (so there are
- * no embedded nulls at all). Also all masked out cells become zeros.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- * \param data_type data type
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_raster_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
- {
- return get_map_row(fd, buf, row, data_type, 0, 1);
- }
- /*!
- * \brief Get raster row (CELL type)
- *
- * Reads a row of raster data and leaves the NULL values intact. (As
- * opposed to the deprecated function G_get_map_row() which
- * converts NULL values to zero.)
- *
- * <b>NOTE.</b> When the raster map is old and null file doesn't
- * exist, it is assumed that all 0-cells are no-data. When map is
- * floating point, uses quant rules set explicitly by
- * G_set_quant_rules() or stored in map's quant file to convert floats
- * to integers.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_c_raster_row(int fd, CELL * buf, int row)
- {
- return G_get_raster_row(fd, buf, row, CELL_TYPE);
- }
- /*!
- * \brief Get raster row (FCELL type)
- *
- * Read a row from the raster map open on <em>fd</em> into the
- * <tt>float</tt> array <em>fcell</em> performing type conversions as
- * necessary based on the actual storage type of the map. Masking,
- * resampling into the current region. NULL-values are always
- * embedded in <tt>fcell</tt> (<em>never converted to a value</em>).
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_f_raster_row(int fd, FCELL * buf, int row)
- {
- return G_get_raster_row(fd, buf, row, FCELL_TYPE);
- }
- /*!
- * \brief Get raster row (DCELL type)
- *
- * Same as G_get_f_raster_row() except that the array <em>dcell</em>
- * is <tt>double</tt>.
- *
- * \param fd file descriptor for the opened raster map
- * \param buf buffer for the row to be placed into
- * \param row data row desired
- *
- * \return 1 on success
- * \return 0 row requested not within window
- * \return -1 on error
- */
- int G_get_d_raster_row(int fd, DCELL * buf, int row)
- {
- return G_get_raster_row(fd, buf, row, DCELL_TYPE);
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- static int open_null_read(int fd)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- char *name, *mapset, *dummy;
- int null_fd;
- if (fcb->null_file_exists == 0)
- return -1;
- if (fcb->reclass_flag) {
- name = fcb->reclass.name;
- mapset = fcb->reclass.mapset;
- }
- else {
- name = fcb->name;
- mapset = fcb->mapset;
- }
- dummy = G_find_file_misc("cell_misc", NULL_FILE, name, mapset);
- if (!dummy) {
- /* G_warning("unable to find [%s]",path); */
- fcb->null_file_exists = 0;
- return -1;
- }
- null_fd = G_open_old_misc("cell_misc", NULL_FILE, name, mapset);
- if (null_fd < 0)
- return -1;
- fcb->null_file_exists = 1;
- return null_fd;
- }
- static int read_null_bits(int null_fd, unsigned char *flags, int row,
- int cols, int fd)
- {
- off_t offset;
- ssize_t size;
- int R;
- if (compute_window_row(fd, row, &R) <= 0) {
- G__init_null_bits(flags, cols);
- return 1;
- }
- if (null_fd < 0)
- return -1;
- size = G__null_bitstream_size(cols);
- offset = (off_t) size *R;
- if (lseek(null_fd, offset, SEEK_SET) < 0) {
- G_warning(_("Error reading null row %d"), R);
- return -1;
- }
- if (read(null_fd, flags, size) != size) {
- G_warning(_("Error reading null row %d"), R);
- return -1;
- }
- return 1;
- }
- static void get_null_value_row_nomask(int fd, char *flags, int row)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- int i, j, null_fd;
- if (row > G__.window.rows || row < 0) {
- G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"),
- fcb->name, fcb->mapset, row);
- }
- if ((fcb->min_null_row > row) ||
- (fcb->min_null_row + NULL_ROWS_INMEM - 1 < row))
- /* the null row row is not in memory */
- {
- /* read in NULL_ROWS_INMEM rows from null file
- so that the requested row is between fcb->min_null_row
- and fcb->min_null_row + NULL_ROWS_INMEM */
- fcb->min_null_row = (row / NULL_ROWS_INMEM) * NULL_ROWS_INMEM;
- null_fd = open_null_read(fd);
- for (i = 0; i < NULL_ROWS_INMEM; i++) {
- /* G__.window.rows doesn't have to be a multiple of NULL_ROWS_INMEM */
- if (i + fcb->min_null_row >= G__.window.rows)
- break;
- if (read_null_bits(null_fd, fcb->null_work_buf,
- i + fcb->min_null_row, fcb->cellhd.cols,
- fd) < 0) {
- if (fcb->map_type == CELL_TYPE) {
- /*
- If can't read null row, assume that all map 0's are nulls
- use allocated G__.mask_buf to read map row */
- get_map_row_nomask(fd, (void *)G__.mask_buf,
- i + fcb->min_null_row, CELL_TYPE);
- for (j = 0; j < G__.window.cols; j++) {
- if (G__.mask_buf[j] == 0)
- flags[j] = 1;
- else
- flags[j] = 0;
- }
- }
- else { /* fp map */
- /* if can't read null row, assume that all data is valid */
- G_zero(flags, sizeof(char) * G__.window.cols);
- /* the flags row is ready now */
- }
- } /*if no null file */
- else {
- /* copy null row to flags row translated by window column mapping */
- /* the fcb->NULL_ROWS[row-fcb->min_null_row] has G__.window.cols bits, */
- /* the fcb->null_work_buf has size fcb->cellhd.cols */
- for (j = 0; j < G__.window.cols; j++) {
- if (!fcb->col_map[j])
- flags[j] = 1;
- else
- flags[j] = G__check_null_bit(fcb->null_work_buf,
- fcb->col_map[j] - 1,
- fcb->cellhd.cols);
- }
- }
- /* remember the null row for i for the future reference */
- /*bf-We should take of the size - or we get
- zeros running on their own after flags convertions -A.Sh. */
- fcb->NULL_ROWS[i] = G_realloc(fcb->NULL_ROWS[i],
- G__null_bitstream_size(G__.window.
- cols) + 1);
- if (fcb->NULL_ROWS[i] == NULL)
- G_fatal_error("get_null_value_row_nomask: %s",
- _("Unable to realloc buffer"));
- G__convert_01_flags(flags, fcb->NULL_ROWS[i], G__.window.cols);
- } /* for loop */
- if (null_fd > 0)
- close(null_fd);
- } /* row is not in memory */
- /* copy null file data translated by column mapping to user null row */
- /* the user requested flags row is of size G__.window.cols */
- G__convert_flags_01(flags, fcb->NULL_ROWS[row - fcb->min_null_row],
- G__.window.cols);
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- static void embed_mask(char *flags, int row)
- {
- int i;
- if (G__.auto_mask <= 0)
- return;
- if (get_map_row_nomask(G__.mask_fd, G__.mask_buf, row, CELL_TYPE) < 0)
- return;
- if (G__.fileinfo[G__.mask_fd].reclass_flag)
- do_reclass_int(G__.mask_fd, G__.mask_buf, 1);
- for (i = 0; i < G__.window.cols; i++)
- if (G__.mask_buf[i] == 0)
- flags[i] = 1;
- }
- static void get_null_value_row(int fd, char *flags, int row, int with_mask)
- {
- get_null_value_row_nomask(fd, flags, row);
- if (with_mask)
- embed_mask(flags, row);
- }
- static int embed_nulls(int fd, void *buf, int row, RASTER_MAP_TYPE map_type,
- int null_is_zero, int with_mask)
- {
- struct fileinfo *fcb = &G__.fileinfo[fd];
- int i;
- /* this is because without null file the nulls can be only due to 0's
- in data row or mask */
- if (null_is_zero && !fcb->null_file_exists
- && (G__.auto_mask <= 0 || !with_mask))
- return 1;
- get_null_value_row(fd, G__.null_buf, row, with_mask);
- for (i = 0; i < G__.window.cols; i++) {
- /* also check for nulls which might be already embedded by quant
- rules in case of fp map. */
- if (G__.null_buf[i] || G_is_null_value(buf, map_type)) {
- /* G__set_[f/d]_null_value() sets it to 0 is the embedded mode
- is not set and calls G_set_[f/d]_null_value() otherwise */
- G__set_null_value(buf, 1, null_is_zero, map_type);
- }
- buf = G_incr_void_ptr(buf, G_raster_size(map_type));
- }
- return 1;
- }
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /*!
- \brief Read or simmulate null value row
- Read or simmulate null value row and set the cells corresponding
- to null value to 1. The masked out cells are set to null when the
- mask exists. (the MASK is taken care of by null values
- (if the null file doesn't exist for this map, then the null row
- is simulated by assuming that all zeros in raster map are nulls.
- Also all masked out cells become nulls.
- \param fd file descriptor for the opened map
- \param buf buffer for the row to be placed into
- \param row data row desired
- \return 1
- */
- int G_get_null_value_row(int fd, char *flags, int row)
- {
- get_null_value_row(fd, flags, row, 1);
- return 1;
- }
|