quant_io.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*!
  2. * \file lib/raster/quant_io.c
  3. *
  4. * \brief Raster Library - Quantization rules (input / output)
  5. *
  6. * (C) 1999-2010 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public License
  9. * (>=v2). Read the file COPYING that comes with GRASS for details.
  10. *
  11. * \author USACERL and many others
  12. */
  13. /**********************************************************************
  14. *
  15. **********************************************************************/
  16. #include <string.h>
  17. #include <grass/gis.h>
  18. #include <grass/raster.h>
  19. #include <grass/glocale.h>
  20. #define QUANT_FILE_NAME "f_quant"
  21. static int quant_parse_file(FILE *, struct Quant *);
  22. #if 0
  23. /* redundant: integer range doesn't exist now: it is defined by
  24. the quant rules */
  25. static int quant_load_range(struct Quant *quant, const char *name, const char *mapset)
  26. {
  27. struct FPRange fprange;
  28. struct Range range;
  29. char buf[300];
  30. DCELL dMin, dMax;
  31. CELL min, max;
  32. if (Rast_read_fp_range(name, mapset, &fprange) <= 0)
  33. return 0;
  34. Rast_get_fp_range_min_max(&fprange, &dMin, &dMax);
  35. if (Rast_is_d_null_value(&dMin) || Rast_is_d_null_value(&dMax)) {
  36. G_warning(_("Floating data range for raster map <%s> is empty"),
  37. G_fully_qualified_name(name, mapset));
  38. return -3;
  39. }
  40. if (Rast_read_range(name, mapset, &range) < 0)
  41. return 0;
  42. Rast_get_range_min_max(&range, &min, &max);
  43. if (Rast_is_c_null_value(&min) && Rast_is_c_null_value(&max)) {
  44. G_warning(_("Integer data range for raster map <%s> is empty"),
  45. G_fully_qualified_name(name, mapset));
  46. return -3;
  47. }
  48. Rast_quant_add_rule(quant, dMin, dMax, min, max);
  49. return 1;
  50. }
  51. #endif
  52. /*!
  53. \brief Reads quantization rules (internal use only)
  54. Reads quantization rules for raster map <i>name</i> in <i>mapset</i>
  55. and stores them in the quantization structure "quant". If the map is
  56. in another mapset, first checks for quant2 table for this map in
  57. current mapset.
  58. Note: in the case of negative return value, the result of using the
  59. quantization structure is not defined.
  60. in case of return value 0, calls to Rast_quant_perform_d()
  61. and Rast_quant_perform_f() return NO_DATA (see description of
  62. Rast_quant_perform_d() for more details). in case of
  63. return values 2 and 3, the explicit rule for quant is set:
  64. floating range is mapped to integer range.
  65. Note: use Rast_quant_init() to allocate and initialize the quantization
  66. staructure quant before the first usage of G_quant_import().
  67. Note: this function uses Rast_quant_free () to clear all previously
  68. stored rules in quant.
  69. \param name map name
  70. \param mapset mapset name
  71. \param[out] quant pointer to Quant structure
  72. \return -2 if raster map is of type integer.
  73. \return -1 if map name is fully qualified and mapset is not the current one
  74. \return 0 if quantization file does not exist, or the file is empty,
  75. \return 1 if non-empty quantization file exists.
  76. */
  77. int Rast__quant_import(const char *name, const char *mapset,
  78. struct Quant *quant)
  79. {
  80. char buf[1024];
  81. char xname[GNAME_MAX], xmapset[GMAPSET_MAX], element[GNAME_MAX + 7];
  82. int parsStat;
  83. FILE *fd;
  84. Rast_quant_free(quant);
  85. if (Rast_map_type(name, mapset) == CELL_TYPE) {
  86. G_warning(_("Attempt to open quantization"
  87. " table for CELL raster map <%s>"),
  88. G_fully_qualified_name(name, mapset));
  89. return -2;
  90. }
  91. if (G_name_is_fully_qualified(name, xname, xmapset)) {
  92. if (strlen(mapset) == 0)
  93. mapset = xmapset;
  94. else if (strcmp(xmapset, mapset) != 0)
  95. return -1;
  96. name = xname;
  97. }
  98. /* first check if quant2/mapset/name exists in the current mapset */
  99. sprintf(element, "quant2/%s", mapset);
  100. if ((fd = G_fopen_old(element, name, G_mapset()))) {
  101. parsStat = quant_parse_file(fd, quant);
  102. fclose(fd);
  103. if (parsStat)
  104. return 1;
  105. sprintf(buf,
  106. "quantization file in quant2 for raster map <%s> is empty",
  107. G_fully_qualified_name(name, mapset));
  108. }
  109. /* now try reading regular : cell_misc/name/quant file */
  110. if (!(fd = G_fopen_old_misc("cell_misc", QUANT_FILE_NAME, name, mapset))) {
  111. /* int range doesn't exist anymore if (quant_load_range (quant, name, mapset)>0) return 3; */
  112. G_warning(_("Quantization file for raster map <%s> is missing"),
  113. G_fully_qualified_name(name, mapset));
  114. }
  115. else {
  116. parsStat = quant_parse_file(fd, quant);
  117. fclose(fd);
  118. if (parsStat)
  119. return 1;
  120. /* int range doesn't exist anymore if (quant_load_range (quant, name, mapset)>0) return 2; */
  121. G_warning(_("Quantization file for raster map <%s> is empty"),
  122. G_fully_qualified_name(name, mapset));
  123. }
  124. return 0;
  125. }
  126. /*!
  127. \brief Parse input lines with the following formats
  128. \code
  129. d_high:d_low:c_high:c_low
  130. d_high:d_low:c_val (i.e. c_high == c_low)
  131. *:d_val:c_val (interval [inf, d_val]) (**)
  132. d_val:*:c_val (interval [d_val, inf]) (**)
  133. \endcode
  134. All other lines are ignored
  135. (**) only the first appearances in the file are considered.
  136. */
  137. static int quant_parse_file(FILE * fd, struct Quant *quant)
  138. {
  139. CELL cLow, cHigh;
  140. DCELL dLow, dHigh;
  141. char buf[1024];
  142. int foundNegInf = 0, foundPosInf = 0;
  143. while (fgets(buf, sizeof(buf), fd)) {
  144. if (strncmp(buf, "truncate", 8) == 0) {
  145. quant->truncate_only = 1;
  146. return 1;
  147. }
  148. if (strncmp(buf, "round", 5) == 0) {
  149. quant->round_only = 1;
  150. return 1;
  151. }
  152. switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &cLow, &cHigh)) {
  153. case 3:
  154. Rast_quant_add_rule(quant, dLow, dHigh, cLow, cLow);
  155. break;
  156. case 4:
  157. Rast_quant_add_rule(quant, dLow, dHigh, cLow, cHigh);
  158. break;
  159. default:
  160. switch (sscanf(buf, "*:%lf:%d", &dLow, &cLow)) {
  161. case 2:
  162. if (!foundNegInf) {
  163. Rast_quant_set_neg_infinite_rule(quant, dLow, cLow);
  164. foundNegInf = 1;
  165. }
  166. break;
  167. default:
  168. switch (sscanf(buf, "%lf:*:%d", &dLow, &cLow)) {
  169. case 2:
  170. if (!foundPosInf) {
  171. Rast_quant_set_pos_infinite_rule(quant, dLow, cLow);
  172. foundPosInf = 1;
  173. }
  174. break;
  175. default:
  176. continue; /* other lines are ignored */
  177. }
  178. }
  179. }
  180. }
  181. if (Rast_quant_nof_rules(quant) > 0)
  182. Rast_quant_reverse_rule_order(quant);
  183. return ((Rast_quant_nof_rules(quant) > 0) ||
  184. (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0) ||
  185. (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0));
  186. }
  187. static void quant_write(FILE * fd, const struct Quant *quant)
  188. {
  189. DCELL dLow, dHigh;
  190. CELL cLow, cHigh;
  191. int i;
  192. if (quant->truncate_only) {
  193. fprintf(fd, "truncate");
  194. return;
  195. }
  196. if (quant->round_only) {
  197. fprintf(fd, "round");
  198. return;
  199. }
  200. if (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0)
  201. fprintf(fd, "*:%.20g:%d\n", dLow, cLow);
  202. if (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0)
  203. fprintf(fd, "%.20g:*:%d\n", dLow, cLow);
  204. for (i = Rast_quant_nof_rules(quant) - 1; i >= 0; i--) {
  205. Rast_quant_get_ith_rule(quant, i, &dLow, &dHigh, &cLow, &cHigh);
  206. fprintf(fd, "%.20g:%.20g:%d", dLow, dHigh, cLow);
  207. if (cLow != cHigh)
  208. fprintf(fd, ":%d", cHigh);
  209. fprintf(fd, "\n");
  210. }
  211. }
  212. /*!
  213. \brief Writes the quantization rules (internal use only)
  214. Writes the quantization rules stored in <i>quant</i> for <i>name</i>
  215. . If the mapset is the same as the current mapset, the quant file is
  216. created in 'cell_misc/name' directory, otherwise it is created in
  217. 'quant2/mapset' directory, much like writing colors for map in
  218. another mapset. The rules are written in decreasing order of
  219. priority (i.e. rules added earlier are written later).
  220. Note: if no rules are defined an empty file is created.
  221. \param name map name
  222. \param mapset mapset name
  223. \param quant pointer to Quant structure
  224. \return -1 if map name is not fully qualified or file could not be opened.
  225. \return 1 otherwise.
  226. */
  227. int Rast__quant_export(const char *name, const char *mapset,
  228. const struct Quant *quant)
  229. {
  230. char element[GNAME_MAX + 7];
  231. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  232. FILE *fd;
  233. if (G_name_is_fully_qualified(name, xname, xmapset)) {
  234. if (strcmp(xmapset, mapset) != 0)
  235. return -1;
  236. name = xname;
  237. }
  238. if (strcmp(G_mapset(), mapset) == 0) {
  239. G_remove_misc("cell_misc", QUANT_FILE_NAME, name);
  240. G__make_mapset_element_misc("cell_misc", name);
  241. if (!(fd = G_fopen_new_misc("cell_misc", QUANT_FILE_NAME, name)))
  242. return -1;
  243. }
  244. else {
  245. sprintf(element, "quant2/%s", mapset);
  246. G_remove(element, name);
  247. G_make_mapset_element(element);
  248. if (!(fd = G_fopen_new(element, name)))
  249. return -1;
  250. }
  251. quant_write(fd, quant);
  252. fclose(fd);
  253. return 1;
  254. }