color_rule.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*!
  2. * \file raster/color_rule.c
  3. *
  4. * \brief Raster Library - Color rules.
  5. *
  6. * (C) 2001-2009 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 Original author CERL
  12. */
  13. #include <grass/gis.h>
  14. #include <grass/raster.h>
  15. #define LIMIT(x) if (x < 0) x = 0; else if (x > 255) x = 255;
  16. static void add_color_rule(const void *, int, int, int,
  17. const void *, int, int, int,
  18. struct _Color_Info_ *, int,
  19. DCELL *, DCELL *, RASTER_MAP_TYPE);
  20. /*!
  21. * \brief Adds the floating-point rule (DCELL version)
  22. *
  23. * See Rast_add_color_rule() for details.
  24. *
  25. * \param v1 cell value
  26. * \param r1,g1,b1 color value
  27. * \param v2 cell value
  28. * \param r2,g2,b2 color value
  29. * \param[in,out] colors pointer to color table structure
  30. * \return
  31. */
  32. void Rast_add_d_color_rule(const DCELL * val1, int r1, int g1, int b1,
  33. const DCELL * val2, int r2, int g2, int b2,
  34. struct Colors *colors)
  35. {
  36. add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->fixed,
  37. colors->version, &colors->cmin, &colors->cmax, DCELL_TYPE);
  38. }
  39. /*!
  40. * \brief Adds the floating-point rule (FCELL version)
  41. *
  42. * See Rast_add_color_rule() for details.
  43. *
  44. * \param v1 cell value
  45. * \param r1,g1,b1 color value
  46. * \param v2 cell value
  47. * \param r2,g2,b2 color value
  48. * \param[in,out] colors pointer to color table structure
  49. * \return
  50. */
  51. void Rast_add_f_color_rule(const FCELL * cat1, int r1, int g1, int b1,
  52. const FCELL * cat2, int r2, int g2, int b2,
  53. struct Colors *colors)
  54. {
  55. add_color_rule(cat1, r1, g1, b1, cat2, r2, g2, b2, &colors->fixed,
  56. colors->version, &colors->cmin, &colors->cmax, FCELL_TYPE);
  57. }
  58. /*!
  59. * \brief Adds the floating-point rule (CCELL version)
  60. *
  61. * See Rast_add_color_rule() for details.
  62. *
  63. * \param v1 cell value
  64. * \param r1,g1,b1 color value
  65. * \param v2 cell value
  66. * \param r2,g2,b2 color value
  67. * \param[in,out] colors pointer to color table structure
  68. * \return
  69. */
  70. void Rast_add_c_color_rule(const CELL * cat1, int r1, int g1, int b1,
  71. const CELL * cat2, int r2, int g2, int b2,
  72. struct Colors *colors)
  73. {
  74. add_color_rule(cat1, r1, g1, b1, cat2, r2, g2, b2, &colors->fixed,
  75. colors->version, &colors->cmin, &colors->cmax, CELL_TYPE);
  76. }
  77. /*!
  78. * \brief Adds the floating-point rule
  79. *
  80. * Adds the floating-point rule that the range [<em>v1,v2</em>] gets a
  81. * linear ramp of colors from [<em>r1,g1,b1</em>] to
  82. * [<em>r2,g2,b2</em>].
  83. * If either <em>v1</em> or <em>v2</em> is the NULL-value, this call is converted into
  84. * <tt>Rast_set_null_value_color (r1, g1, b1, colors)</tt>
  85. *
  86. * - If <em>map_type</em> is CELL_TYPE, calls Rast_add_c_color_rule()
  87. * - If <em>map_type</em> is FCELL_TYPE, calls Rast_add_f_color_rule()
  88. * - If <em>map_type</em> is DCELL_TYPE, calls Rast_add_d_color_rule()
  89. *
  90. * \param v1 cell value
  91. * \param r1,g1,b1 color value
  92. * \param v2 cell value
  93. * \param r2,g2,b2 color value
  94. * \param[in,out] colors pointer to color table structure
  95. * \param data_type raster data type (CELL, FCELL, DCELL)
  96. * \return
  97. */
  98. void Rast_add_color_rule(const void *val1, int r1, int g1, int b1,
  99. const void *val2, int r2, int g2, int b2,
  100. struct Colors *colors, RASTER_MAP_TYPE data_type)
  101. {
  102. add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->fixed,
  103. colors->version, &colors->cmin, &colors->cmax, data_type);
  104. }
  105. /*!
  106. * \brief Add modular color rule (DCELL version)
  107. *
  108. * \param val1 cell value
  109. * \param r1,g1,b1 color value
  110. * \param val2 cell value
  111. * \param r2,g2,b2 color value
  112. * \param[in,out] colors pointer to color table structure
  113. *
  114. * \return -1 on failure
  115. * \return 1 on success
  116. */
  117. int Rast_add_modular_d_color_rule(const DCELL * val1, int r1, int g1, int b1,
  118. const DCELL * val2, int r2, int g2, int b2,
  119. struct Colors *colors)
  120. {
  121. DCELL min, max;
  122. if (colors->version < 0)
  123. return -1; /* can't use this on 3.0 colors */
  124. min = colors->cmin;
  125. max = colors->cmax;
  126. add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
  127. &colors->cmin, &colors->cmax, DCELL_TYPE);
  128. colors->cmin = min; /* don't reset these */
  129. colors->cmax = max;
  130. return 1;
  131. }
  132. /*!
  133. * \brief Add modular color rule (FCELL version)
  134. *
  135. * \param val1 cell value
  136. * \param r1,g1,b1 color value
  137. * \param val2 cell value
  138. * \param r2,g2,b2 color value
  139. * \param[in,out] colors pointer to color table structure
  140. *
  141. * \return -1 on failure
  142. * \return 1 on success
  143. */
  144. int Rast_add_modular_f_color_rule(const FCELL * val1, int r1, int g1, int b1,
  145. const FCELL * val2, int r2, int g2, int b2,
  146. struct Colors *colors)
  147. {
  148. DCELL min, max;
  149. if (colors->version < 0)
  150. return -1; /* can;t use this on 3.0 colors */
  151. min = colors->cmin;
  152. max = colors->cmax;
  153. add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
  154. &colors->cmin, &colors->cmax, FCELL_TYPE);
  155. colors->cmin = min; /* don't reset these */
  156. colors->cmax = max;
  157. return 1;
  158. }
  159. /*!
  160. * \brief Add modular color rule (CELL version)
  161. *
  162. * \param val1 cell value
  163. * \param r1,g1,b1 color value
  164. * \param val2 cell value
  165. * \param r2,g2,b2 color value
  166. * \param[in,out] colors pointer to color table structure
  167. *
  168. * \return -1 on failure
  169. * \return 1 on success
  170. */
  171. int Rast_add_modular_c_color_rule(const CELL * val1, int r1, int g1, int b1,
  172. const CELL * val2, int r2, int g2, int b2,
  173. struct Colors *colors)
  174. {
  175. CELL min, max;
  176. if (colors->version < 0)
  177. return -1; /* can;t use this on 3.0 colors */
  178. min = colors->cmin;
  179. max = colors->cmax;
  180. add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
  181. &colors->cmin, &colors->cmax, CELL_TYPE);
  182. colors->cmin = min; /* don't reset these */
  183. colors->cmax = max;
  184. return 1;
  185. }
  186. /*!
  187. * \brief Add modular color rule
  188. *
  189. * \todo Question: shouldn't this function call
  190. * G_add_modular_<data_type>_raster_color_rule() instead?
  191. *
  192. * \param val1 cell value
  193. * \param r1,g1,b1 color value
  194. * \param val2 cell value
  195. * \param r2,g2,b2 color value
  196. * \param[in,out] colors pointer to color table structure
  197. * \param data_type raster data type
  198. *
  199. * \return -1 on failure
  200. * \return 1 on success
  201. */
  202. int Rast_add_modular_color_rule(const void *val1, int r1, int g1, int b1,
  203. const void *val2, int r2, int g2, int b2,
  204. struct Colors *colors,
  205. RASTER_MAP_TYPE data_type)
  206. {
  207. CELL min, max;
  208. if (colors->version < 0)
  209. return -1; /* can't use this on 3.0 colors */
  210. min = colors->cmin;
  211. max = colors->cmax;
  212. add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
  213. &colors->cmin, &colors->cmax, data_type);
  214. colors->cmin = min; /* don't reset these */
  215. colors->cmax = max;
  216. return 1;
  217. }
  218. static void add_color_rule(const void *pt1, int r1, int g1, int b1,
  219. const void *pt2, int r2, int g2, int b2,
  220. struct _Color_Info_ *cp, int version, DCELL * cmin,
  221. DCELL * cmax, RASTER_MAP_TYPE data_type)
  222. {
  223. struct _Color_Rule_ *rule, *next;
  224. unsigned char red, grn, blu;
  225. DCELL min, max, val1, val2;
  226. CELL cat;
  227. val1 = Rast_get_d_value(pt1, data_type);
  228. val2 = Rast_get_d_value(pt2, data_type);
  229. /* allocate a low:high rule */
  230. rule = (struct _Color_Rule_ *)G_malloc(sizeof(*rule));
  231. rule->next = rule->prev = NULL;
  232. /* make sure colors are in the range [0,255] */
  233. LIMIT(r1);
  234. LIMIT(g1);
  235. LIMIT(b1);
  236. LIMIT(r2);
  237. LIMIT(g2);
  238. LIMIT(b2);
  239. /* val1==val2, use average color */
  240. /* otherwise make sure low < high */
  241. if (val1 == val2) {
  242. rule->low.value = rule->high.value = val1;
  243. rule->low.red = rule->high.red = (r1 + r2) / 2;
  244. rule->low.grn = rule->high.grn = (g1 + g2) / 2;
  245. rule->low.blu = rule->high.blu = (b1 + b2) / 2;
  246. }
  247. else if (val1 < val2) {
  248. rule->low.value = val1;
  249. rule->low.red = r1;
  250. rule->low.grn = g1;
  251. rule->low.blu = b1;
  252. rule->high.value = val2;
  253. rule->high.red = r2;
  254. rule->high.grn = g2;
  255. rule->high.blu = b2;
  256. }
  257. else {
  258. rule->low.value = val2;
  259. rule->low.red = r2;
  260. rule->low.grn = g2;
  261. rule->low.blu = b2;
  262. rule->high.value = val1;
  263. rule->high.red = r1;
  264. rule->high.grn = g1;
  265. rule->high.blu = b1;
  266. }
  267. /* keep track of the overall min and max, excluding null */
  268. if (Rast_is_d_null_value(&(rule->low.value)))
  269. return;
  270. if (Rast_is_d_null_value(&(rule->high.value)))
  271. return;
  272. min = rule->low.value;
  273. max = rule->high.value;
  274. if (min <= max) {
  275. if (cp->min > cp->max) {
  276. cp->min = min;
  277. cp->max = max;
  278. }
  279. else {
  280. if (cp->min > min)
  281. cp->min = min;
  282. if (cp->max < max)
  283. cp->max = max;
  284. }
  285. }
  286. if (*cmin > *cmax) {
  287. *cmin = cp->min;
  288. *cmax = cp->max;
  289. }
  290. else {
  291. if (*cmin > cp->min)
  292. *cmin = cp->min;
  293. if (*cmax < cp->max)
  294. *cmax = cp->max;
  295. }
  296. /* If version is old style (i.e., pre 4.0),
  297. * interpolate this rule from min to max
  298. * and insert each cat into the lookup table.
  299. * Then free the rule.
  300. * Otherwise, free the lookup table, if active.
  301. * G_organize_colors() will regenerate it
  302. * Link this rule into the list of rules
  303. */
  304. if (version < 0) {
  305. for (cat = (CELL) min; cat <= (CELL) max; cat++) {
  306. Rast__interpolate_color_rule((DCELL) cat, &red, &grn, &blu, rule);
  307. Rast__insert_color_into_lookup(cat, (int)red, (int)grn, (int)blu,
  308. cp);
  309. }
  310. G_free(rule);
  311. }
  312. else {
  313. if (cp->rules)
  314. cp->rules->prev = rule;
  315. rule->next = cp->rules;
  316. cp->rules = rule;
  317. /* prune the rules:
  318. * remove all rules that are contained by this rule
  319. */
  320. min = rule->low.value; /* mod 4.1 */
  321. max = rule->high.value; /* mod 4.1 */
  322. cp->n_rules++;
  323. for (rule = rule->next; rule; rule = next) {
  324. next = rule->next; /* has to be done here, not in for stmt */
  325. if (min <= rule->low.value && max >= rule->high.value) {
  326. if ((rule->prev->next = next)) /* remove from the list */
  327. next->prev = rule->prev;
  328. G_free(rule);
  329. cp->n_rules--;
  330. }
  331. }
  332. /* free lookup array, if allocated */
  333. Rast__color_free_lookup(cp);
  334. Rast__color_free_fp_lookup(cp);
  335. }
  336. }