quant_io.c 9.0 KB

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