sparse.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. ** Bitmap library
  3. **
  4. ** Written by David Gerdes 12 November 1992
  5. ** US Army Construction Engineering Research Laboratories
  6. **
  7. **
  8. ** This library provides basic support for the creation and manipulation
  9. ** of two dimensional bitmap arrays.
  10. **
  11. ** BM_create (x, y) Create bitmap of specified dimensions
  12. **
  13. ** BM_destroy (map) Destroy bitmap and free memory
  14. **
  15. ** BM_set (map, x, y, val) Set array position to val [TRUE/FALSE]
  16. **
  17. ** BM_get (map, x, y) Return value at array position
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <grass/linkm.h>
  22. #include <grass/bitmap.h>
  23. #define BM_col_to_byte(x) ((x)/8)
  24. #define BM_col_to_bit(x) ((x)%8)
  25. static int depth;
  26. /*!
  27. * \brief
  28. *
  29. * Create a sparse bitmap of dimension 'x'/'y'
  30. *
  31. * Returns bitmap structure or NULL on error
  32. *
  33. * \param x
  34. * \param y
  35. * \return struct BM
  36. */
  37. struct BM *
  38. BM_create_sparse (int x, int y)
  39. {
  40. struct BM *map;
  41. int i;
  42. if (NULL == (map = (struct BM *) malloc (sizeof (struct BM))))
  43. return (NULL);
  44. map->bytes = (x+7)/8;
  45. if (NULL == (map->data = (unsigned char *)
  46. malloc ( sizeof (struct BMlink *) * y )))
  47. return (NULL);
  48. map->rows = y;
  49. map->cols = x;
  50. map->sparse = 1;
  51. link_set_chunk_size (500);
  52. map->token = link_init (sizeof (struct BMlink));
  53. for (i = 0 ; i < map->rows ; i++)
  54. {
  55. ((struct BMlink **) (map->data))[i] = (struct BMlink *) link_new (map->token);
  56. ((struct BMlink **) (map->data))[i]->count = x;
  57. ((struct BMlink **) (map->data))[i]->val = 0;
  58. ((struct BMlink **) (map->data))[i]->next = NULL;
  59. }
  60. depth++;
  61. return map;
  62. }
  63. /*!
  64. * \brief
  65. *
  66. * Destroy sparse bitmap and free all associated memory
  67. *
  68. * Returns 0
  69. *
  70. * \param map
  71. * \return int
  72. */
  73. int BM_destroy_sparse (struct BM *map)
  74. {
  75. int i;
  76. struct BMlink *p, *tmp;
  77. for (i = 0 ; i < map->rows ; i++)
  78. {
  79. p = ((struct BMlink **) (map->data))[i];
  80. while (p != NULL)
  81. {
  82. tmp = p->next;
  83. link_dispose (map->token,(VOID_T *) p);
  84. p = tmp;
  85. }
  86. }
  87. if (--depth == 0)
  88. link_cleanup (map->token);
  89. free (map->data);
  90. free (map);
  91. return 0;
  92. }
  93. /*!
  94. * \brief
  95. *
  96. * Set sparse bitmap value to 'val' at location 'x'/'y'
  97. *
  98. * Returns 0
  99. *
  100. * \param map
  101. * \param x
  102. * \param y
  103. * \param val
  104. * \return int
  105. */
  106. int
  107. BM_set_sparse (struct BM *map, int x, int y, int val)
  108. {
  109. struct BMlink *p, *p2, *prev;
  110. int cur_x = 0;
  111. int Tcount, Tval;
  112. int dist_a, dist_b;
  113. val = !(!val); /* set val == 1 or 0 */
  114. p = ((struct BMlink **) (map->data))[y];
  115. prev = NULL;
  116. while (p != NULL)
  117. {
  118. if (cur_x + p->count > x)
  119. {
  120. if (p->val == val) /* no change */
  121. return 0;
  122. Tcount = p->count; /* save current state */
  123. Tval = p->val;
  124. /* if x is on edge, then we probably want to merge it with
  125. ** its neighbor for efficiency
  126. */
  127. /* dist_a is how far x is from Left edge of group */
  128. /* dist_b is how far x is from right edge of group */
  129. dist_a = x - cur_x;
  130. dist_b = (cur_x + p->count - 1) - x;
  131. /* if on both edges, then we should be able to merge 3 into one */
  132. if (dist_b == 0 && p->next && p->next->val == val)
  133. {
  134. if (dist_a == 0 && x > 0)
  135. {
  136. if (prev != NULL && prev->val == val)
  137. {
  138. prev->count += p->next->count + 1;
  139. prev->next = p->next->next;
  140. link_dispose (map->token, (VOID_T *) p->next);
  141. link_dispose (map->token, (VOID_T *)p);
  142. return 0;
  143. }
  144. }
  145. }
  146. /* handle right edge merge */
  147. if (dist_b == 0 && p->next && p->next->val == val)
  148. {
  149. p->count--;
  150. p->next->count++;
  151. if (p->count == 0)
  152. {
  153. if (prev)
  154. {
  155. prev->next = p->next;
  156. }
  157. else
  158. {
  159. ((struct BMlink **) (map->data))[y] = p->next;
  160. }
  161. link_dispose (map->token, (VOID_T *)p);
  162. }
  163. return 0;
  164. }
  165. /* handle left edge merge */
  166. if (dist_a == 0 && x > 0)
  167. {
  168. if (prev != NULL && prev->val == val)
  169. {
  170. prev->count++;
  171. p->count--;
  172. if (p->count == 0)
  173. {
  174. prev->next = p->next;
  175. link_dispose (map->token, (VOID_T *)p);
  176. }
  177. return 0;
  178. }
  179. }
  180. /* if not on edge, have to add link for each side */
  181. if (dist_a > 0)
  182. {
  183. p->count = dist_a;
  184. p->val = Tval;
  185. p2 = (struct BMlink *) link_new (map->token);
  186. p2->next = p->next;
  187. p->next = p2;
  188. p = p2;
  189. }
  190. p->count = 1;
  191. p->val = val;
  192. if (dist_b > 0)
  193. {
  194. p2 = (struct BMlink *) link_new (map->token);
  195. p2->count = dist_b;
  196. p2->val = Tval;
  197. p2->next = p->next;
  198. p->next = p2;
  199. }
  200. return 0;
  201. }
  202. cur_x += p->count;
  203. prev = p;
  204. p = p->next;
  205. }
  206. return 0;
  207. }
  208. /*!
  209. * \brief
  210. *
  211. * Returns sparse bitmap value at location 'x'/'y'
  212. *
  213. * Returns value or -1 on error
  214. *
  215. * \param map
  216. * \param x
  217. * \param y
  218. * \return int
  219. */
  220. int
  221. BM_get_sparse (struct BM *map, int x, int y)
  222. {
  223. struct BMlink *p;
  224. int cur_x = 0;
  225. p = ((struct BMlink **) (map->data))[y];
  226. while (p != NULL)
  227. {
  228. if (cur_x + p->count > x)
  229. return (p->val);
  230. cur_x += p->count;
  231. p = p->next;
  232. }
  233. return -1;
  234. }
  235. /*!
  236. * \brief
  237. *
  238. * Returns size of sparse bitmap in bytes
  239. *
  240. * \param map
  241. * \return int
  242. */
  243. int
  244. BM_get_map_size_sparse (struct BM *map)
  245. {
  246. int i;
  247. int size;
  248. struct BMlink *p;
  249. size = map->rows * sizeof (struct BMlink *);
  250. for (i = 0 ; i < map->rows ; i++)
  251. {
  252. p = ((struct BMlink **) (map->data))[i];
  253. while (p != NULL)
  254. {
  255. size += sizeof (struct BMlink);
  256. p = p->next;
  257. }
  258. }
  259. return size;
  260. }
  261. /*!
  262. * \brief
  263. *
  264. * Debugging code to dump out structure of links
  265. *
  266. * Returns 0
  267. *
  268. * \param map
  269. * \return int
  270. */
  271. int
  272. BM_dump_map_sparse (struct BM *map)
  273. {
  274. int i;
  275. struct BMlink *p;
  276. for (i = 0 ; i < map->rows ; i++)
  277. {
  278. p = ((struct BMlink **) (map->data))[i];
  279. while (p != NULL)
  280. {
  281. fprintf (stdout, "(%2d %2d) ", p->count, p->val);
  282. p = p->next;
  283. }
  284. fprintf (stdout, "\n");
  285. }
  286. return 0;
  287. }
  288. /*!
  289. * \brief
  290. *
  291. * Debugging code to dump out structure of links for single row
  292. *
  293. * Returns 0
  294. *
  295. * \param map
  296. * \param y
  297. * \return int
  298. */
  299. int
  300. BM_dump_map_row_sparse (struct BM *map, int y)
  301. {
  302. int i;
  303. struct BMlink *p;
  304. i = y;
  305. {
  306. p = ((struct BMlink **) (map->data))[i];
  307. while (p != NULL)
  308. {
  309. fprintf (stdout, "(%2d %2d) ", p->count, p->val);
  310. p = p->next;
  311. }
  312. fprintf (stdout, "\n");
  313. }
  314. return 0;
  315. }
  316. /*!
  317. * \brief
  318. *
  319. * Write sparse bitmap matrix out to disk file 'fp'.
  320. * NOTE: 'fp' must already be opened and later closed by user
  321. *
  322. * Returns 0 on success or -1 on error
  323. *
  324. * \param fp
  325. * \param map
  326. * \return int
  327. */
  328. int
  329. BM_file_write_sparse (FILE *fp, struct BM *map)
  330. {
  331. char c;
  332. int i, y;
  333. struct BMlink *p;
  334. int cnt;
  335. c = BM_MAGIC;
  336. fwrite (&c, sizeof(char), sizeof(char), fp);
  337. fwrite (BM_TEXT, BM_TEXT_LEN, sizeof(char), fp);
  338. c = BM_SPARSE;
  339. fwrite (&c, sizeof(char), sizeof(char), fp);
  340. fwrite (&(map->rows), sizeof (map->rows), sizeof(char), fp);
  341. fwrite (&(map->cols), sizeof (map->cols), sizeof(char), fp);
  342. for (y = 0 ; y < map->rows ; y++)
  343. {
  344. /* first count number of links */
  345. p = ((struct BMlink **) (map->data))[y];
  346. cnt = 0;
  347. while (p != NULL)
  348. {
  349. cnt++;
  350. p = p->next;
  351. }
  352. i = cnt;
  353. fwrite (&i, sizeof (i), sizeof(char), fp);
  354. /* then write them out */
  355. p = ((struct BMlink **) (map->data))[y];
  356. while (p != NULL)
  357. {
  358. i = p->count;
  359. fwrite (&i, sizeof (i), sizeof(char), fp);
  360. i = p->val;
  361. fwrite (&i, sizeof (i), sizeof(char), fp);
  362. p = p->next;
  363. }
  364. }
  365. fflush (fp);
  366. return 0;
  367. }