get_row.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. /*!
  2. \file get_row.c
  3. \brief GIS library - get raster row
  4. (C) 2003-2008 by the GRASS Development Team
  5. This program is free software under the
  6. GNU General Public License (>=v2).
  7. Read the file COPYING that comes with GRASS
  8. for details.
  9. \author Original author CERL
  10. */
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <sys/types.h>
  14. #include <rpc/types.h> /* need this for sgi */
  15. #include <rpc/xdr.h>
  16. #include <grass/config.h>
  17. #include <grass/glocale.h>
  18. #include "G.h"
  19. /*--------------------------------------------------------------------------*/
  20. #define NULL_FILE "null"
  21. /*--------------------------------------------------------------------------*/
  22. static int embed_nulls(int, void *, int, RASTER_MAP_TYPE, int, int);
  23. /*--------------------------------------------------------------------------*/
  24. static int compute_window_row(int fd, int row, int *cellRow)
  25. {
  26. struct fileinfo *fcb = &G__.fileinfo[fd];
  27. double f;
  28. int r;
  29. /* check for row in window */
  30. if (row < 0 || row >= G__.window.rows) {
  31. G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"),
  32. fcb->name, fcb->mapset, row);
  33. return -1;
  34. }
  35. /* convert window row to cell file row */
  36. f = row * fcb->C1 + fcb->C2;
  37. r = (int)f;
  38. if (f < r) /* adjust for rounding up of negatives */
  39. r--;
  40. if (r < 0 || r >= fcb->cellhd.rows)
  41. return 0;
  42. *cellRow = r;
  43. return 1;
  44. }
  45. /*--------------------------------------------------------------------------*/
  46. static void do_reclass_int(int fd, void *cell, int null_is_zero)
  47. {
  48. struct fileinfo *fcb = &G__.fileinfo[fd];
  49. CELL *c = cell;
  50. CELL *reclass_table = fcb->reclass.table;
  51. CELL min = fcb->reclass.min;
  52. CELL max = fcb->reclass.max;
  53. int i;
  54. for (i = 0; i < G__.window.cols; i++) {
  55. if (G_is_c_null_value(&c[i])) {
  56. if (null_is_zero)
  57. c[i] = 0;
  58. continue;
  59. }
  60. if (c[i] < min || c[i] > max) {
  61. if (null_is_zero)
  62. c[i] = 0;
  63. else
  64. G_set_c_null_value(&c[i], 1);
  65. continue;
  66. }
  67. c[i] = reclass_table[c[i] - min];
  68. if (null_is_zero && G_is_c_null_value(&c[i]))
  69. c[i] = 0;
  70. }
  71. }
  72. /*--------------------------------------------------------------------------*/
  73. static int read_data_fp_compressed(int fd, int row, unsigned char *data_buf,
  74. int *nbytes)
  75. {
  76. struct fileinfo *fcb = &G__.fileinfo[fd];
  77. off_t t1 = fcb->row_ptr[row];
  78. off_t t2 = fcb->row_ptr[row + 1];
  79. size_t readamount = t2 - t1;
  80. size_t bufsize = fcb->cellhd.cols * fcb->nbytes;
  81. if (lseek(fd, t1, SEEK_SET) < 0)
  82. return -1;
  83. *nbytes = fcb->nbytes;
  84. if ((size_t) G_zlib_read(fd, readamount, data_buf, bufsize) != bufsize)
  85. return -1;
  86. return 0;
  87. }
  88. /*--------------------------------------------------------------------------*/
  89. static void rle_decompress(unsigned char *dst, const unsigned char *src,
  90. int nbytes, int size)
  91. {
  92. int pairs = size / (nbytes + 1);
  93. int i;
  94. for (i = 0; i < pairs; i++) {
  95. int repeat = *src++;
  96. int j;
  97. for (j = 0; j < repeat; j++) {
  98. memcpy(dst, src, nbytes);
  99. dst += nbytes;
  100. }
  101. src += nbytes;
  102. }
  103. }
  104. static int read_data_compressed(int fd, int row, unsigned char *data_buf,
  105. int *nbytes)
  106. {
  107. struct fileinfo *fcb = &G__.fileinfo[fd];
  108. off_t t1 = fcb->row_ptr[row];
  109. off_t t2 = fcb->row_ptr[row + 1];
  110. ssize_t readamount = t2 - t1;
  111. unsigned char *cmp = G__.compressed_buf;
  112. int n;
  113. if (lseek(fd, t1, SEEK_SET) < 0)
  114. return -1;
  115. if (read(fd, cmp, readamount) != readamount)
  116. return -1;
  117. /* Now decompress the row */
  118. if (fcb->cellhd.compressed > 0) {
  119. /* one byte is nbyte count */
  120. n = *nbytes = *cmp++;
  121. readamount--;
  122. }
  123. else
  124. /* pre 3.0 compression */
  125. n = *nbytes = fcb->nbytes;
  126. if (fcb->cellhd.compressed < 0 || readamount < n * fcb->cellhd.cols) {
  127. if (fcb->cellhd.compressed == 2)
  128. G_zlib_expand(cmp, readamount, data_buf, n * fcb->cellhd.cols);
  129. else
  130. rle_decompress(data_buf, cmp, n, readamount);
  131. }
  132. else
  133. memcpy(data_buf, cmp, readamount);
  134. return 0;
  135. }
  136. /*--------------------------------------------------------------------------*/
  137. static int read_data_uncompressed(int fd, int row, unsigned char *data_buf,
  138. int *nbytes)
  139. {
  140. struct fileinfo *fcb = &G__.fileinfo[fd];
  141. ssize_t bufsize = fcb->cellhd.cols * fcb->nbytes;
  142. *nbytes = fcb->nbytes;
  143. if (lseek(fd, (off_t) row * bufsize, SEEK_SET) == -1)
  144. return -1;
  145. if (read(fd, data_buf, bufsize) != bufsize)
  146. return -1;
  147. return 0;
  148. }
  149. /*--------------------------------------------------------------------------*/
  150. /* Actually read a row of data in */
  151. static int read_data(int fd, int row, unsigned char *data_buf, int *nbytes)
  152. {
  153. struct fileinfo *fcb = &G__.fileinfo[fd];
  154. if (!fcb->cellhd.compressed)
  155. return read_data_uncompressed(fd, row, data_buf, nbytes);
  156. /* map is in compressed form */
  157. if (fcb->map_type == CELL_TYPE)
  158. return read_data_compressed(fd, row, data_buf, nbytes);
  159. else
  160. return read_data_fp_compressed(fd, row, data_buf, nbytes);
  161. }
  162. /*--------------------------------------------------------------------------*/
  163. /* copy cell file data to user buffer translated by window column mapping */
  164. static void cell_values_int(int fd, const unsigned char *data,
  165. const COLUMN_MAPPING * cmap, int nbytes,
  166. void *cell, int n)
  167. {
  168. CELL *c = cell;
  169. COLUMN_MAPPING cmapold = 0;
  170. int big = (size_t) nbytes >= sizeof(CELL);
  171. int i;
  172. for (i = 0; i < n; i++) {
  173. const unsigned char *d;
  174. int neg;
  175. CELL v;
  176. int j;
  177. if (!cmap[i]) {
  178. c[i] = 0;
  179. continue;
  180. }
  181. if (cmap[i] == cmapold) {
  182. c[i] = c[i - 1];
  183. continue;
  184. }
  185. d = data + (cmap[i] - 1) * nbytes;
  186. if (big && (*d & 0x80)) {
  187. neg = 1;
  188. v = *d++ & 0x7f;
  189. }
  190. else {
  191. neg = 0;
  192. v = *d++;
  193. }
  194. for (j = 1; j < nbytes; j++)
  195. v = (v << 8) + *d++;
  196. c[i] = neg ? -v : v;
  197. cmapold = cmap[i];
  198. }
  199. }
  200. /*--------------------------------------------------------------------------*/
  201. static void cell_values_float(int fd, const unsigned char *data,
  202. const COLUMN_MAPPING * cmap, int nbytes,
  203. void *cell, int n)
  204. {
  205. struct fileinfo *fcb = &G__.fileinfo[fd];
  206. FCELL *c = cell;
  207. COLUMN_MAPPING cmapold = 0;
  208. XDR *xdrs = &fcb->xdrstream;
  209. int i;
  210. /* xdr stream is initialized to read from */
  211. /* fcb->data in 'opencell.c' */
  212. xdr_setpos(xdrs, 0);
  213. for (i = 0; i < n; i++) {
  214. if (!cmap[i]) {
  215. c[i] = 0;
  216. continue;
  217. }
  218. if (cmap[i] == cmapold) {
  219. c[i] = c[i - 1];
  220. continue;
  221. }
  222. if (cmap[i] < cmapold) {
  223. xdr_setpos(xdrs, 0);
  224. cmapold = 0;
  225. }
  226. while (cmapold++ != cmap[i]) /* skip */
  227. if (!xdr_float(xdrs, &c[i]))
  228. G_fatal_error(_("cell_values_float: xdr_float failed for index %d"),
  229. i);
  230. cmapold--;
  231. }
  232. }
  233. /*--------------------------------------------------------------------------*/
  234. static void cell_values_double(int fd, const unsigned char *data,
  235. const COLUMN_MAPPING * cmap, int nbytes,
  236. void *cell, int n)
  237. {
  238. struct fileinfo *fcb = &G__.fileinfo[fd];
  239. DCELL *c = cell;
  240. COLUMN_MAPPING cmapold = 0;
  241. XDR *xdrs = &fcb->xdrstream;
  242. int i;
  243. /* xdr stream is initialized to read from */
  244. /* fcb->data in 'opencell.c' */
  245. xdr_setpos(xdrs, 0);
  246. for (i = 0; i < n; i++) {
  247. if (!cmap[i]) {
  248. c[i] = 0;
  249. continue;
  250. }
  251. if (cmap[i] == cmapold) {
  252. c[i] = c[i - 1];
  253. continue;
  254. }
  255. if (cmap[i] < cmapold) {
  256. xdr_setpos(xdrs, 0);
  257. cmapold = 0;
  258. }
  259. while (cmapold++ != cmap[i]) /* skip */
  260. if (!xdr_double(xdrs, &c[i]))
  261. G_fatal_error(_("cell_values_double: xdr_double failed for index %d"),
  262. i);
  263. cmapold--;
  264. }
  265. }
  266. /*--------------------------------------------------------------------------*/
  267. /*--------------------------------------------------------------------------*/
  268. /*--------------------------------------------------------------------------*/
  269. /* transfer_to_cell_XY takes bytes from fcb->data, converts these bytes with
  270. the appropriate procedure (e.g. XDR or byte reordering) into type X
  271. values which are put into array G__.work_buf.
  272. finally the values in G__.work_buf are converted into
  273. type Y and put into 'cell'.
  274. if type X == type Y the intermediate step of storing the values in
  275. G__.work_buf might be ommited. check the appropriate function for XY to
  276. determine the procedure of conversion.
  277. */
  278. /*--------------------------------------------------------------------------*/
  279. static void transfer_to_cell_XX(int fd, void *cell)
  280. {
  281. static void (*cell_values_type[3]) () = {
  282. cell_values_int, cell_values_float, cell_values_double};
  283. struct fileinfo *fcb = &G__.fileinfo[fd];
  284. (cell_values_type[fcb->map_type]) (fd, fcb->data, fcb->col_map,
  285. fcb->cur_nbytes, cell,
  286. G__.window.cols);
  287. }
  288. /*--------------------------------------------------------------------------*/
  289. static void transfer_to_cell_fi(int fd, void *cell)
  290. {
  291. struct fileinfo *fcb = &G__.fileinfo[fd];
  292. int i;
  293. transfer_to_cell_XX(fd, G__.work_buf);
  294. for (i = 0; i < G__.window.cols; i++)
  295. ((CELL *) cell)[i] = (fcb->col_map[i] == 0)
  296. ? 0
  297. : G_quant_get_cell_value(&fcb->quant,
  298. ((FCELL *) G__.work_buf)[i]);
  299. }
  300. static void transfer_to_cell_di(int fd, void *cell)
  301. {
  302. struct fileinfo *fcb = &G__.fileinfo[fd];
  303. int i;
  304. transfer_to_cell_XX(fd, G__.work_buf);
  305. for (i = 0; i < G__.window.cols; i++)
  306. ((CELL *) cell)[i] = (fcb->col_map[i] == 0)
  307. ? 0
  308. : G_quant_get_cell_value(&fcb->quant,
  309. ((DCELL *) G__.work_buf)[i]);
  310. }
  311. /*--------------------------------------------------------------------------*/
  312. static void transfer_to_cell_if(int fd, void *cell)
  313. {
  314. int i;
  315. transfer_to_cell_XX(fd, G__.work_buf);
  316. for (i = 0; i < G__.window.cols; i++)
  317. ((FCELL *) cell)[i] = ((CELL *) G__.work_buf)[i];
  318. }
  319. static void transfer_to_cell_df(int fd, void *cell)
  320. {
  321. int i;
  322. transfer_to_cell_XX(fd, G__.work_buf);
  323. for (i = 0; i < G__.window.cols; i++)
  324. ((FCELL *) cell)[i] = ((DCELL *) G__.work_buf)[i];
  325. }
  326. /*--------------------------------------------------------------------------*/
  327. static void transfer_to_cell_id(int fd, void *cell)
  328. {
  329. int i;
  330. transfer_to_cell_XX(fd, G__.work_buf);
  331. for (i = 0; i < G__.window.cols; i++)
  332. ((DCELL *) cell)[i] = ((CELL *) G__.work_buf)[i];
  333. }
  334. static void transfer_to_cell_fd(int fd, void *cell)
  335. {
  336. int i;
  337. transfer_to_cell_XX(fd, G__.work_buf);
  338. for (i = 0; i < G__.window.cols; i++)
  339. ((DCELL *) cell)[i] = ((FCELL *) G__.work_buf)[i];
  340. }
  341. /*--------------------------------------------------------------------------*/
  342. /*--------------------------------------------------------------------------*/
  343. /*--------------------------------------------------------------------------*/
  344. /*
  345. * works for all map types and doesn't consider
  346. * null row corresponding to the requested row
  347. */
  348. static int get_map_row_nomask(int fd, void *rast, int row,
  349. RASTER_MAP_TYPE data_type)
  350. {
  351. static void (*transfer_to_cell_FtypeOtype[3][3]) () = { {
  352. transfer_to_cell_XX, transfer_to_cell_if, transfer_to_cell_id}, {
  353. transfer_to_cell_fi, transfer_to_cell_XX, transfer_to_cell_fd}, {
  354. transfer_to_cell_di, transfer_to_cell_df, transfer_to_cell_XX}};
  355. struct fileinfo *fcb = &G__.fileinfo[fd];
  356. int r;
  357. int rowStatus;
  358. rowStatus = compute_window_row(fd, row, &r);
  359. if (rowStatus <= 0) {
  360. fcb->cur_row = -1;
  361. G_zero_raster_buf(rast, data_type);
  362. return rowStatus;
  363. }
  364. /* read cell file row if not in memory */
  365. if (r != fcb->cur_row) {
  366. fcb->cur_row = r;
  367. if (read_data(fd, fcb->cur_row, fcb->data, &fcb->cur_nbytes) < 0) {
  368. G_zero_raster_buf(rast, data_type);
  369. if (!fcb->io_error) {
  370. if (fcb->cellhd.compressed)
  371. G_warning(_("Error reading compressed map <%s@%s>, row %d"),
  372. fcb->name, fcb->mapset, r);
  373. else
  374. G_warning(_("Error reading map <%s@%s>, row %d"),
  375. fcb->name, fcb->mapset, r);
  376. fcb->io_error = 1;
  377. }
  378. return -1;
  379. }
  380. }
  381. (transfer_to_cell_FtypeOtype[fcb->map_type][data_type]) (fd, rast);
  382. return 1;
  383. }
  384. /*--------------------------------------------------------------------------*/
  385. static int get_map_row_no_reclass(int fd, void *rast, int row,
  386. RASTER_MAP_TYPE data_type, int null_is_zero,
  387. int with_mask)
  388. {
  389. int stat;
  390. stat = get_map_row_nomask(fd, rast, row, data_type);
  391. if (stat < 0)
  392. return stat;
  393. stat = embed_nulls(fd, rast, row, data_type, null_is_zero, with_mask);
  394. if (stat < 0)
  395. return stat;
  396. return 1;
  397. }
  398. /*--------------------------------------------------------------------------*/
  399. static int get_map_row(int fd, void *rast, int row, RASTER_MAP_TYPE data_type,
  400. int null_is_zero, int with_mask)
  401. {
  402. struct fileinfo *fcb = &G__.fileinfo[fd];
  403. int size = G_raster_size(data_type);
  404. void *buf;
  405. int type;
  406. int stat;
  407. int i;
  408. if (fcb->reclass_flag && data_type != CELL_TYPE) {
  409. buf = G__.temp_buf;
  410. type = CELL_TYPE;
  411. }
  412. else {
  413. buf = rast;
  414. type = data_type;
  415. }
  416. stat =
  417. get_map_row_no_reclass(fd, buf, row, type, null_is_zero, with_mask);
  418. if (stat < 0)
  419. return stat;
  420. if (!fcb->reclass_flag)
  421. return 1;
  422. /* if the map is reclass table, get and
  423. reclass CELL row and copy results to needed type */
  424. do_reclass_int(fd, buf, null_is_zero);
  425. if (data_type == CELL_TYPE)
  426. return 1;
  427. for (i = 0; i < G__.window.cols; i++) {
  428. G_set_raster_value_c(rast, G__.temp_buf[i], data_type);
  429. rast = G_incr_void_ptr(rast, size);
  430. }
  431. return 1;
  432. }
  433. /*--------------------------------------------------------------------------*/
  434. /*--------------------------------------------------------------------------*/
  435. /*--------------------------------------------------------------------------*/
  436. /*!
  437. * \brief Read raster row without masking (this routine is deprecated)
  438. *
  439. * This routine reads the specified <em>row</em> from the raster map
  440. * open on file descriptor <em>fd</em> into the <em>buf</em> buffer
  441. * like G_get_map_row() does. The difference is that masking is
  442. * suppressed. If the user has a mask set, G_get_map_row() will apply
  443. * the mask but G_get_map_row_nomask() will ignore it. This routine
  444. * prints a diagnostic message and returns -1 if there is an error
  445. * reading the raster map. Otherwise a nonnegative value is returned.
  446. *
  447. * <b>Note.</b> Ignoring the mask is not generally acceptable. Users
  448. * expect the mask to be applied. However, in some cases ignoring the
  449. * mask is justified. For example, the GRASS modules
  450. * <i>r.describe</i>, which reads the raster map directly to report
  451. * all data values in a raster map, and <i>r.slope.aspect</i>, which
  452. * produces slope and aspect from elevation, ignore both the mask and
  453. * the region. However, the number of GRASS modules which do this
  454. * should be minimal. See Mask for more information about the mask.
  455. *
  456. * <b>This routine is deprecated! Use G_get_raster_row_nomask()
  457. * instead.</b>
  458. *
  459. * \param fd file descriptor for the opened raster map
  460. * \param buf buffer for the row to be placed into
  461. * \param row data row desired
  462. *
  463. * \return 1 on success
  464. * \return 0 row requested not within window
  465. * \return -1 on error
  466. */
  467. int G_get_map_row_nomask(int fd, CELL * buf, int row)
  468. {
  469. return get_map_row(fd, buf, row, CELL_TYPE, 1, 0);
  470. }
  471. /*!
  472. * \brief Read raster row without masking
  473. *
  474. * Same as G_get_raster_row() except no masking occurs.
  475. *
  476. * \param fd file descriptor for the opened raster map
  477. * \param buf buffer for the row to be placed into
  478. * \param row data row desired
  479. * \param data_type data type
  480. *
  481. * \return 1 on success
  482. * \return 0 row requested not within window
  483. * \return -1 on error
  484. */
  485. int G_get_raster_row_nomask(int fd, void *buf, int row,
  486. RASTER_MAP_TYPE data_type)
  487. {
  488. return get_map_row(fd, buf, row, data_type, 0, 0);
  489. }
  490. /*!
  491. * \brief Read raster row without masking (CELL type)
  492. *
  493. * Same as G_get_c_raster_row() except no masking occurs.
  494. *
  495. * \param fd file descriptor for the opened raster map
  496. * \param buf buffer for the row to be placed into
  497. * \param row data row desired
  498. * \param data_type data type
  499. *
  500. * \return 1 on success
  501. * \return 0 row requested not within window
  502. * \return -1 on error
  503. */
  504. int G_get_c_raster_row_nomask(int fd, CELL * buf, int row)
  505. {
  506. return G_get_raster_row_nomask(fd, buf, row, CELL_TYPE);
  507. }
  508. /*!
  509. * \brief Read raster row without masking (FCELL type)
  510. *
  511. * Same as G_get_f_raster_row() except no masking occurs.
  512. *
  513. * \param fd file descriptor for the opened raster map
  514. * \param buf buffer for the row to be placed into
  515. * \param row data row desired
  516. * \param data_type data type
  517. *
  518. * \return 1 on success
  519. * \return 0 row requested not within window
  520. * \return -1 on error
  521. */
  522. int G_get_f_raster_row_nomask(int fd, FCELL * buf, int row)
  523. {
  524. return G_get_raster_row_nomask(fd, buf, row, FCELL_TYPE);
  525. }
  526. /*!
  527. * \brief Read raster row without masking (DCELL type)
  528. *
  529. * Same as G_get_d_raster_row() except no masking occurs.
  530. *
  531. * \param fd file descriptor for the opened raster map
  532. * \param buf buffer for the row to be placed into
  533. * \param row data row desired
  534. * \param data_type data type
  535. *
  536. * \return 1 on success
  537. * \return 0 row requested not within window
  538. * \return -1 on error
  539. */
  540. int G_get_d_raster_row_nomask(int fd, DCELL * buf, int row)
  541. {
  542. return G_get_raster_row_nomask(fd, buf, row, DCELL_TYPE);
  543. }
  544. /*--------------------------------------------------------------------------*/
  545. /*!
  546. * \brief Get raster row (this routine is deprecated!)
  547. *
  548. * If the map is floating-point, quantize the floating-point values to
  549. * integer using the quantization rules established for the map when
  550. * the map was opened for reading (this quantization is read from
  551. * cell_misc/name/f_quant file, but can be reset after opening raster
  552. * map by G_set_quant_rules()). NULL values are converted to zeros.
  553. *
  554. * <b>This routine is deprecated! Use G_get_raster_row() instead.</b>
  555. *
  556. * \param fd file descriptor for the opened raster map
  557. * \param buf buffer for the row to be placed into
  558. * \param row data row desired
  559. *
  560. * \return 1 on success
  561. * \return 0 row requested not within window
  562. * \return -1 on error
  563. */
  564. int G_get_map_row(int fd, CELL * buf, int row)
  565. {
  566. return get_map_row(fd, buf, row, CELL_TYPE, 1, 1);
  567. }
  568. /*!
  569. * \brief Get raster row
  570. *
  571. * If <em>data_type</em> is
  572. * - CELL_TYPE, calls G_get_c_raster_row()
  573. * - FCELL_TYPE, calls G_get_f_raster_row()
  574. * - DCELL_TYPE, calls G_get_d_raster_row()
  575. *
  576. * Reads appropriate information into the buffer <em>buf</em> associated
  577. * with the requested row <em>row</em>. <em>buf</em> is associated with the
  578. * current window.
  579. *
  580. * Note, that the type of the data in <em>buf</em> (say X) is independent of
  581. * the type of the data in the file described by <em>fd</em> (say Y).
  582. *
  583. * - Step 1: Read appropriate raw map data into a intermediate buffer.
  584. * - Step 2: Convert the data into a CPU readable format, and subsequently
  585. * resample the data. the data is stored in a second intermediate
  586. * buffer (the type of the data in this buffer is Y).
  587. * - Step 3: Convert this type Y data into type X data and store it in
  588. * buffer "buf". Conversion is performed in functions
  589. * "transfer_to_cell_XY". (For details of the conversion between
  590. * two particular types check the functions).
  591. * - Step 4: read or simmulate null value row and zero out cells corresponding
  592. * to null value cells. The masked out cells are set to null when the
  593. * mask exists. (the MASK is taken care of by null values
  594. * (if the null file doesn't exist for this map, then the null row
  595. * is simulated by assuming that all zero are nulls *** in case
  596. * of G_get_raster_row() and assuming that all data is valid
  597. * in case of G_get_f/d_raster_row(). In case of deprecated function
  598. * G_get_map_row() all nulls are converted to zeros (so there are
  599. * no embedded nulls at all). Also all masked out cells become zeros.
  600. *
  601. * \param fd file descriptor for the opened raster map
  602. * \param buf buffer for the row to be placed into
  603. * \param row data row desired
  604. * \param data_type data type
  605. *
  606. * \return 1 on success
  607. * \return 0 row requested not within window
  608. * \return -1 on error
  609. */
  610. int G_get_raster_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
  611. {
  612. return get_map_row(fd, buf, row, data_type, 0, 1);
  613. }
  614. /*!
  615. * \brief Get raster row (CELL type)
  616. *
  617. * Reads a row of raster data and leaves the NULL values intact. (As
  618. * opposed to the deprecated function G_get_map_row() which
  619. * converts NULL values to zero.)
  620. *
  621. * <b>NOTE.</b> When the raster map is old and null file doesn't
  622. * exist, it is assumed that all 0-cells are no-data. When map is
  623. * floating point, uses quant rules set explicitly by
  624. * G_set_quant_rules() or stored in map's quant file to convert floats
  625. * to integers.
  626. *
  627. * \param fd file descriptor for the opened raster map
  628. * \param buf buffer for the row to be placed into
  629. * \param row data row desired
  630. *
  631. * \return 1 on success
  632. * \return 0 row requested not within window
  633. * \return -1 on error
  634. */
  635. int G_get_c_raster_row(int fd, CELL * buf, int row)
  636. {
  637. return G_get_raster_row(fd, buf, row, CELL_TYPE);
  638. }
  639. /*!
  640. * \brief Get raster row (FCELL type)
  641. *
  642. * Read a row from the raster map open on <em>fd</em> into the
  643. * <tt>float</tt> array <em>fcell</em> performing type conversions as
  644. * necessary based on the actual storage type of the map. Masking,
  645. * resampling into the current region. NULL-values are always
  646. * embedded in <tt>fcell</tt> (<em>never converted to a value</em>).
  647. *
  648. * \param fd file descriptor for the opened raster map
  649. * \param buf buffer for the row to be placed into
  650. * \param row data row desired
  651. *
  652. * \return 1 on success
  653. * \return 0 row requested not within window
  654. * \return -1 on error
  655. */
  656. int G_get_f_raster_row(int fd, FCELL * buf, int row)
  657. {
  658. return G_get_raster_row(fd, buf, row, FCELL_TYPE);
  659. }
  660. /*!
  661. * \brief Get raster row (DCELL type)
  662. *
  663. * Same as G_get_f_raster_row() except that the array <em>dcell</em>
  664. * is <tt>double</tt>.
  665. *
  666. * \param fd file descriptor for the opened raster map
  667. * \param buf buffer for the row to be placed into
  668. * \param row data row desired
  669. *
  670. * \return 1 on success
  671. * \return 0 row requested not within window
  672. * \return -1 on error
  673. */
  674. int G_get_d_raster_row(int fd, DCELL * buf, int row)
  675. {
  676. return G_get_raster_row(fd, buf, row, DCELL_TYPE);
  677. }
  678. /*--------------------------------------------------------------------------*/
  679. /*--------------------------------------------------------------------------*/
  680. /*--------------------------------------------------------------------------*/
  681. static int open_null_read(int fd)
  682. {
  683. struct fileinfo *fcb = &G__.fileinfo[fd];
  684. char *name, *mapset, *dummy;
  685. int null_fd;
  686. if (fcb->null_file_exists == 0)
  687. return -1;
  688. if (fcb->reclass_flag) {
  689. name = fcb->reclass.name;
  690. mapset = fcb->reclass.mapset;
  691. }
  692. else {
  693. name = fcb->name;
  694. mapset = fcb->mapset;
  695. }
  696. dummy = G_find_file_misc("cell_misc", NULL_FILE, name, mapset);
  697. if (!dummy) {
  698. /* G_warning("unable to find [%s]",path); */
  699. fcb->null_file_exists = 0;
  700. return -1;
  701. }
  702. null_fd = G_open_old_misc("cell_misc", NULL_FILE, name, mapset);
  703. if (null_fd < 0)
  704. return -1;
  705. fcb->null_file_exists = 1;
  706. return null_fd;
  707. }
  708. static int read_null_bits(int null_fd, unsigned char *flags, int row,
  709. int cols, int fd)
  710. {
  711. off_t offset;
  712. ssize_t size;
  713. int R;
  714. if (compute_window_row(fd, row, &R) <= 0) {
  715. G__init_null_bits(flags, cols);
  716. return 1;
  717. }
  718. if (null_fd < 0)
  719. return -1;
  720. size = G__null_bitstream_size(cols);
  721. offset = (off_t) size *R;
  722. if (lseek(null_fd, offset, SEEK_SET) < 0) {
  723. G_warning(_("Error reading null row %d"), R);
  724. return -1;
  725. }
  726. if (read(null_fd, flags, size) != size) {
  727. G_warning(_("Error reading null row %d"), R);
  728. return -1;
  729. }
  730. return 1;
  731. }
  732. static void get_null_value_row_nomask(int fd, char *flags, int row)
  733. {
  734. struct fileinfo *fcb = &G__.fileinfo[fd];
  735. int i, j, null_fd;
  736. if (row > G__.window.rows || row < 0) {
  737. G_warning(_("Reading raster map <%s@%s> request for row %d is outside region"),
  738. fcb->name, fcb->mapset, row);
  739. }
  740. if ((fcb->min_null_row > row) ||
  741. (fcb->min_null_row + NULL_ROWS_INMEM - 1 < row))
  742. /* the null row row is not in memory */
  743. {
  744. /* read in NULL_ROWS_INMEM rows from null file
  745. so that the requested row is between fcb->min_null_row
  746. and fcb->min_null_row + NULL_ROWS_INMEM */
  747. fcb->min_null_row = (row / NULL_ROWS_INMEM) * NULL_ROWS_INMEM;
  748. null_fd = open_null_read(fd);
  749. for (i = 0; i < NULL_ROWS_INMEM; i++) {
  750. /* G__.window.rows doesn't have to be a multiple of NULL_ROWS_INMEM */
  751. if (i + fcb->min_null_row >= G__.window.rows)
  752. break;
  753. if (read_null_bits(null_fd, fcb->null_work_buf,
  754. i + fcb->min_null_row, fcb->cellhd.cols,
  755. fd) < 0) {
  756. if (fcb->map_type == CELL_TYPE) {
  757. /*
  758. If can't read null row, assume that all map 0's are nulls
  759. use allocated G__.mask_buf to read map row */
  760. get_map_row_nomask(fd, (void *)G__.mask_buf,
  761. i + fcb->min_null_row, CELL_TYPE);
  762. for (j = 0; j < G__.window.cols; j++) {
  763. if (G__.mask_buf[j] == 0)
  764. flags[j] = 1;
  765. else
  766. flags[j] = 0;
  767. }
  768. }
  769. else { /* fp map */
  770. /* if can't read null row, assume that all data is valid */
  771. G_zero(flags, sizeof(char) * G__.window.cols);
  772. /* the flags row is ready now */
  773. }
  774. } /*if no null file */
  775. else {
  776. /* copy null row to flags row translated by window column mapping */
  777. /* the fcb->NULL_ROWS[row-fcb->min_null_row] has G__.window.cols bits, */
  778. /* the fcb->null_work_buf has size fcb->cellhd.cols */
  779. for (j = 0; j < G__.window.cols; j++) {
  780. if (!fcb->col_map[j])
  781. flags[j] = 1;
  782. else
  783. flags[j] = G__check_null_bit(fcb->null_work_buf,
  784. fcb->col_map[j] - 1,
  785. fcb->cellhd.cols);
  786. }
  787. }
  788. /* remember the null row for i for the future reference */
  789. /*bf-We should take of the size - or we get
  790. zeros running on their own after flags convertions -A.Sh. */
  791. fcb->NULL_ROWS[i] = G_realloc(fcb->NULL_ROWS[i],
  792. G__null_bitstream_size(G__.window.
  793. cols) + 1);
  794. if (fcb->NULL_ROWS[i] == NULL)
  795. G_fatal_error("get_null_value_row_nomask: %s",
  796. _("Unable to realloc buffer"));
  797. G__convert_01_flags(flags, fcb->NULL_ROWS[i], G__.window.cols);
  798. } /* for loop */
  799. if (null_fd > 0)
  800. close(null_fd);
  801. } /* row is not in memory */
  802. /* copy null file data translated by column mapping to user null row */
  803. /* the user requested flags row is of size G__.window.cols */
  804. G__convert_flags_01(flags, fcb->NULL_ROWS[row - fcb->min_null_row],
  805. G__.window.cols);
  806. }
  807. /*--------------------------------------------------------------------------*/
  808. /*--------------------------------------------------------------------------*/
  809. /*--------------------------------------------------------------------------*/
  810. static void embed_mask(char *flags, int row)
  811. {
  812. int i;
  813. if (G__.auto_mask <= 0)
  814. return;
  815. if (get_map_row_nomask(G__.mask_fd, G__.mask_buf, row, CELL_TYPE) < 0)
  816. return;
  817. if (G__.fileinfo[G__.mask_fd].reclass_flag)
  818. do_reclass_int(G__.mask_fd, G__.mask_buf, 1);
  819. for (i = 0; i < G__.window.cols; i++)
  820. if (G__.mask_buf[i] == 0)
  821. flags[i] = 1;
  822. }
  823. static void get_null_value_row(int fd, char *flags, int row, int with_mask)
  824. {
  825. get_null_value_row_nomask(fd, flags, row);
  826. if (with_mask)
  827. embed_mask(flags, row);
  828. }
  829. static int embed_nulls(int fd, void *buf, int row, RASTER_MAP_TYPE map_type,
  830. int null_is_zero, int with_mask)
  831. {
  832. struct fileinfo *fcb = &G__.fileinfo[fd];
  833. int i;
  834. /* this is because without null file the nulls can be only due to 0's
  835. in data row or mask */
  836. if (null_is_zero && !fcb->null_file_exists
  837. && (G__.auto_mask <= 0 || !with_mask))
  838. return 1;
  839. get_null_value_row(fd, G__.null_buf, row, with_mask);
  840. for (i = 0; i < G__.window.cols; i++) {
  841. /* also check for nulls which might be already embedded by quant
  842. rules in case of fp map. */
  843. if (G__.null_buf[i] || G_is_null_value(buf, map_type)) {
  844. /* G__set_[f/d]_null_value() sets it to 0 is the embedded mode
  845. is not set and calls G_set_[f/d]_null_value() otherwise */
  846. G__set_null_value(buf, 1, null_is_zero, map_type);
  847. }
  848. buf = G_incr_void_ptr(buf, G_raster_size(map_type));
  849. }
  850. return 1;
  851. }
  852. /*--------------------------------------------------------------------------*/
  853. /*--------------------------------------------------------------------------*/
  854. /*--------------------------------------------------------------------------*/
  855. /*!
  856. \brief Read or simmulate null value row
  857. Read or simmulate null value row and set the cells corresponding
  858. to null value to 1. The masked out cells are set to null when the
  859. mask exists. (the MASK is taken care of by null values
  860. (if the null file doesn't exist for this map, then the null row
  861. is simulated by assuming that all zeros in raster map are nulls.
  862. Also all masked out cells become nulls.
  863. \param fd file descriptor for the opened map
  864. \param buf buffer for the row to be placed into
  865. \param row data row desired
  866. \return 1
  867. */
  868. int G_get_null_value_row(int fd, char *flags, int row)
  869. {
  870. get_null_value_row(fd, flags, row, 1);
  871. return 1;
  872. }