quant_io.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**********************************************************************
  2. *
  3. * int
  4. * G__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 G_quant_perform_d ()
  24. * and G_quant_perform_f () return NO_DATA (see description of
  25. * G_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 G_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 G_quant_free () to clear all previously
  33. * stored rules in quant.
  34. *
  35. **********************************************************************
  36. *
  37. * int
  38. * G__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 <grass/gis.h>
  59. #include <grass/glocale.h>
  60. #include <string.h>
  61. /*--------------------------------------------------------------------------*/
  62. #define QUANT_FILE_NAME "f_quant"
  63. /*--------------------------------------------------------------------------*/
  64. static int quant_parse_file(FILE *, struct Quant *);
  65. #if 0
  66. static int
  67. /* redundant: integer range doesn't exist now: it is defined by
  68. the quant rules */
  69. quant_load_range(struct Quant *quant, const char *name, const char *mapset)
  70. {
  71. struct FPRange fprange;
  72. struct Range range;
  73. char buf[300];
  74. DCELL dMin, dMax;
  75. CELL min, max;
  76. if (G_read_fp_range(name, mapset, &fprange) <= 0)
  77. return 0;
  78. G_get_fp_range_min_max(&fprange, &dMin, &dMax);
  79. if (G_is_d_null_value(&dMin) || G_is_d_null_value(&dMax)) {
  80. sprintf(buf, _("The floating data range for %s@%s is empty"), name,
  81. mapset);
  82. G_warning(buf);
  83. return -3;
  84. }
  85. if (G_read_range(name, mapset, &range) < 0)
  86. return 0;
  87. G_get_range_min_max(&range, &min, &max);
  88. if (G_is_c_null_value(&min) && G_is_c_null_value(&max)) {
  89. sprintf(buf, _("The integer data range for %s@%s is empty"), name,
  90. mapset);
  91. G_warning(buf);
  92. return -3;
  93. }
  94. G_quant_add_rule(quant, dMin, dMax, min, max);
  95. return 1;
  96. }
  97. #endif
  98. /*--------------------------------------------------------------------------*/
  99. int G__quant_import(const char *name, const char *mapset, struct Quant *quant)
  100. {
  101. char buf[1024];
  102. char *err;
  103. char xname[GNAME_MAX], xmapset[GMAPSET_MAX], element[GNAME_MAX + 7];
  104. int parsStat;
  105. FILE *fd;
  106. G_quant_free(quant);
  107. if (G_raster_map_type(name, mapset) == CELL_TYPE) {
  108. sprintf(buf,
  109. "G__quant_import: attempt to open quantization table for CELL_TYPE file [%s] in mapset {%s]",
  110. name, mapset);
  111. G_warning(buf);
  112. return -2;
  113. }
  114. if (G__name_is_fully_qualified(name, xname, xmapset)) {
  115. if (strcmp(xmapset, mapset) != 0)
  116. return -1;
  117. name = xname;
  118. }
  119. /* first check if quant2/mapset/name exists in the current mapset */
  120. sprintf(element, "quant2/%s", mapset);
  121. if ((fd = G_fopen_old(element, name, G_mapset()))) {
  122. parsStat = quant_parse_file(fd, quant);
  123. fclose(fd);
  124. if (parsStat)
  125. return 1;
  126. sprintf(buf,
  127. "quantization file in quant2 for [%s] in mapset [%s] is empty",
  128. name, mapset);
  129. }
  130. /* now try reading regular : cell_misc/name/quant file */
  131. if (!(fd = G_fopen_old_misc("cell_misc", QUANT_FILE_NAME, name, mapset))) {
  132. /* int range doesn't exist anymore if (quant_load_range (quant, name, mapset)>0) return 3; */
  133. err = "missing";
  134. }
  135. else {
  136. parsStat = quant_parse_file(fd, quant);
  137. fclose(fd);
  138. if (parsStat)
  139. return 1;
  140. /* int range doesn't exist anymore if (quant_load_range (quant, name, mapset)>0) return 2; */
  141. err = "empty";
  142. }
  143. sprintf(buf,
  144. _("quantization file [%s] in mapset [%s] %s"), name, mapset, err);
  145. G_warning(buf);
  146. return 0;
  147. }
  148. /*--------------------------------------------------------------------------*/
  149. /* parse input lines with the following formats
  150. *
  151. * d_high:d_low:c_high:c_low
  152. * d_high:d_low:c_val (i.e. c_high == c_low)
  153. * *:d_val:c_val (interval [inf, d_val]) (**)
  154. * d_val:*:c_val (interval [d_val, inf]) (**)
  155. *
  156. * all other lines are ignored
  157. *
  158. * (**) only the first appearances in the file are considered.
  159. *
  160. */
  161. /*--------------------------------------------------------------------------*/
  162. static int quant_parse_file(FILE * fd, struct Quant *quant)
  163. {
  164. CELL cLow, cHigh;
  165. DCELL dLow, dHigh;
  166. char buf[1024];
  167. int foundNegInf = 0, foundPosInf = 0;
  168. while (fgets(buf, sizeof(buf), fd)) {
  169. if (strncmp(buf, "truncate", 8) == 0) {
  170. quant->truncate_only = 1;
  171. return 1;
  172. }
  173. if (strncmp(buf, "round", 5) == 0) {
  174. quant->round_only = 1;
  175. return 1;
  176. }
  177. switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &cLow, &cHigh)) {
  178. case 3:
  179. G_quant_add_rule(quant, dLow, dHigh, cLow, cLow);
  180. break;
  181. case 4:
  182. G_quant_add_rule(quant, dLow, dHigh, cLow, cHigh);
  183. break;
  184. default:
  185. switch (sscanf(buf, "*:%lf:%d", &dLow, &cLow)) {
  186. case 2:
  187. if (!foundNegInf) {
  188. G_quant_set_neg_infinite_rule(quant, dLow, cLow);
  189. foundNegInf = 1;
  190. }
  191. break;
  192. default:
  193. switch (sscanf(buf, "%lf:*:%d", &dLow, &cLow)) {
  194. case 2:
  195. if (!foundPosInf) {
  196. G_quant_set_pos_infinite_rule(quant, dLow, cLow);
  197. foundPosInf = 1;
  198. }
  199. break;
  200. default:
  201. continue; /* other lines are ignored */
  202. }
  203. }
  204. }
  205. }
  206. if (G_quant_nof_rules(quant) > 0)
  207. G_quant_reverse_rule_order(quant);
  208. return ((G_quant_nof_rules(quant) > 0) ||
  209. (G_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0) ||
  210. (G_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0));
  211. }
  212. /*--------------------------------------------------------------------------*/
  213. /*--------------------------------------------------------------------------*/
  214. static void quant_write(FILE * fd, const struct Quant *quant)
  215. {
  216. DCELL dLow, dHigh;
  217. CELL cLow, cHigh;
  218. int i;
  219. if (quant->truncate_only) {
  220. fprintf(fd, "truncate");
  221. return;
  222. }
  223. if (quant->round_only) {
  224. fprintf(fd, "round");
  225. return;
  226. }
  227. if (G_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0)
  228. fprintf(fd, "*:%.20g:%d\n", dLow, cLow);
  229. if (G_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0)
  230. fprintf(fd, "%.20g:*:%d\n", dLow, cLow);
  231. for (i = G_quant_nof_rules(quant) - 1; i >= 0; i--) {
  232. G_quant_get_ith_rule(quant, i, &dLow, &dHigh, &cLow, &cHigh);
  233. fprintf(fd, "%.20g:%.20g:%d", dLow, dHigh, cLow);
  234. if (cLow != cHigh)
  235. fprintf(fd, ":%d", cHigh);
  236. fprintf(fd, "\n");
  237. }
  238. }
  239. /*--------------------------------------------------------------------------*/
  240. int
  241. G__quant_export(const char *name, const char *mapset,
  242. const struct Quant *quant)
  243. {
  244. char element[GNAME_MAX + 7];
  245. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  246. FILE *fd;
  247. if (G__name_is_fully_qualified(name, xname, xmapset)) {
  248. if (strcmp(xmapset, mapset) != 0)
  249. return -1;
  250. name = xname;
  251. }
  252. if (strcmp(G_mapset(), mapset) == 0) {
  253. G_remove_misc("cell_misc", QUANT_FILE_NAME, name);
  254. G__make_mapset_element_misc("cell_misc", name);
  255. if (!(fd = G_fopen_new_misc("cell_misc", QUANT_FILE_NAME, name)))
  256. return -1;
  257. }
  258. else {
  259. sprintf(element, "quant2/%s", mapset);
  260. G_remove(element, name);
  261. G__make_mapset_element(element);
  262. if (!(fd = G_fopen_new(element, name)))
  263. return -1;
  264. }
  265. quant_write(fd, quant);
  266. fclose(fd);
  267. return 1;
  268. }
  269. /*--------------------------------------------------------------------------*/
  270. /*--------------------------------------------------------------------------*/
  271. /*--------------------------------------------------------------------------*/