GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
bitmap.c
Go to the documentation of this file.
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  ** struct BM *
12  ** BM_create (x, y) Create bitmap of specified dimensions
13  **
14  ** BM_set_mode (mode, size) Specify Mode and data size in bits.
15  ** Affects all further calls to BM_create()
16  ** Mode can be BM_FLAT or BM_SPARSE
17  ** Size can only be 1 currently.
18  **
19  ** BM_destroy (map) Destroy bitmap and free memory
20  **
21  ** BM_set (map, x, y, val) Set array position to val [TRUE/FALSE]
22  **
23  ** BM_get (map, x, y) Return value at array position
24  **
25  **
26  ** BM_file_write (fp, map) Write bitmap to file
27  **
28  ** struct BM *
29  ** BM_file_read (fp) Create bitmap and load from file
30  **
31  ** BM_get_map_size (map) returns size in bytes that bitmap is
32  ** taking up. For diagnosis use.
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <grass/linkm.h>
38 #include <grass/bitmap.h>
39 
40 #define BM_col_to_byte(x) ((x) >> 3) /* x / 8 */
41 #define BM_col_to_bit(x) ((x) & 7) /* x % 8 */
42 
43 static int Mode = BM_FLAT;
44 static int Size = 1;
45 
46 /*!
47  * \brief Create bitmap of dimension x/y and return structure token.
48  *
49  * Bitmap is initialized to all zeros
50  *
51  * \param x x dimension
52  * \param y y dimension
53  *
54  * \return pointer to struct BM
55  * \return NULL on error
56  */
57 struct BM *BM_create(int x, int y)
58 {
59  struct BM *map;
60 
61  if (Mode == BM_SPARSE)
62  return BM_create_sparse(x, y);
63 
64  if (NULL == (map = (struct BM *)malloc(sizeof(struct BM))))
65  return (NULL);
66 
67  map->bytes = (x + 7) / 8;
68 
69  if (NULL ==
70  (map->data = (unsigned char *)calloc(map->bytes * y, sizeof(char)))) {
71  free(map);
72  return (NULL);
73  }
74 
75  map->rows = y;
76  map->cols = x;
77  map->sparse = 0;
78 
79  return map;
80 }
81 
82 /*!
83  * \brief Destroy bitmap and free all associated memory
84  *
85  * \param map
86  * \return int returns 0
87  */
88 int BM_destroy(struct BM *map)
89 {
90  if (map->sparse)
91  return BM_destroy_sparse(map);
92 
93  free(map->data);
94  free(map);
95 
96  return 0;
97 }
98 
99 /*
100  ** Caller can specify type of data structure to use for bitmap, as
101  ** well as the size of the data values. Currently since this is
102  ** the 'bitmap' library, size can ONLY have value 1.
103  ** Size is number of bits of storage per cell.
104  **
105  ** Mode:
106  ** BM_FLAT Your basic packed bitmap, eight values are stored per byte
107  ** Thus you get a 1:8 compression over using char arrays
108  ** and a 1:32 compression over using CELL arrays.
109  **
110  **
111  ** BM_SPARSE Linked array of values. Much more efficient for large
112  ** very sparse arrays. Slower access, especially for writing,
113  ** but can save several orders of magnitude of memory on large
114  ** bitmaps since size of FLAT bitmap is O(M*N)
115  **
116  **
117  ** Returns 0 or negative on error;
118  ** If error it will print a warning message to stderr and continue
119  ** continue by running but will not change the option in error.
120  */
121 
122 /*!
123  * \brief
124  *
125  * Specify the type of data structure to use for bitmap.
126  * 'mode' can be either BM_FLAT or BM_SPARSE:
127  *
128  * BM_FLAT is a basic packed bitmap - eight values stored per byte
129  * thus creating a 1:8 compression over using char arrays and a
130  * 1:32 compression over using CELL arrays.
131  *
132  * BM_SPARSE is a linked array of values. This is much more efficient
133  * for large, very sparse arrays. It is slower to access, especially
134  * for writing, but can save several orders of magnitude of memory on
135  * large bitmaps.
136  *
137  * NOTE: At this time 'size' must be passed a value of 1
138  *
139  * returns 0 on success or -1 on error
140  *
141  * \param mode
142  * \param size
143  * \return int
144  */
145 int BM_set_mode(int mode, int size)
146 {
147  int ret = 0;
148 
149  switch (mode) {
150  case BM_FLAT:
151  case BM_SPARSE:
152  Mode = mode;
153  break;
154  default:
155  fprintf(stderr, "BM_set_mode: Unknown mode: %d\n", mode);
156  ret--;
157  }
158 
159  if (size != 1) {
160  fprintf(stderr, "BM_set_mode: Bad size: %d\n", size);
161  ret--;
162  }
163  else
164  Size = size;
165 
166  return ret;
167 }
168 
169 /*!
170  * \brief
171  *
172  * Sets bitmap value to 'val' at location 'x' 'y'
173  *
174  * Returns 0 on success
175  *
176  * \param map
177  * \param x
178  * \param y
179  * \param val
180  * \return int
181  */
182 int BM_set(struct BM *map, int x, int y, int val)
183 {
184  unsigned char byte;
185 
186  if (x < 0 || x >= map->cols || y < 0 || y >= map->rows)
187  return 0;
188 
189  if (map->sparse)
190  return BM_set_sparse(map, x, y, val);
191 
192  byte = 0x01 << BM_col_to_bit(x);
193  if (val)
194  map->data[BM_col_to_byte(x) + y * map->bytes] |= byte;
195  else
196  map->data[BM_col_to_byte(x) + y * map->bytes] &= ~byte;
197 
198  return 0;
199 }
200 
201 /*!
202  * \brief
203  *
204  * Gets 'val' from the bitmap
205  *
206  * Returns 0 or 1 on success or -1 on error
207  *
208  * \param map
209  * \param x
210  * \param y
211  * \return int
212  */
213 int BM_get(struct BM *map, int x, int y)
214 {
215  unsigned char byte;
216 
217  if (x < 0 || x >= map->cols || y < 0 || y >= map->rows)
218  return -1;
219 
220  if (map->sparse)
221  return BM_get_sparse(map, x, y);
222 
223  byte = map->data[BM_col_to_byte(x) + y * map->bytes];
224 
225  return byte >> BM_col_to_bit(x) & 0x01;
226 }
227 
228 /*!
229  * \brief
230  *
231  * Returns size in bytes that bitmap is taking up.
232  *
233  * \param map
234  * \return int
235  */
236 size_t BM_get_map_size(struct BM *map)
237 {
238  if (map->sparse)
239  return BM_get_map_size_sparse(map);
240 
241  return (size_t)map->bytes * map->rows;
242 }
243 
244 /*!
245  * \brief
246  *
247  * Write bitmap out to file
248  *
249  * Expects open file pointer 'fp' and existing map structure.
250  * Caller is responsible to open and close 'fp'.
251  *
252  * Returns 0 or -1 on error
253  *
254  * \param fp
255  * \param map
256  * \return int
257  */
258 int BM_file_write(FILE *fp, struct BM *map)
259 {
260  char c;
261  int i;
262 
263  if (map->sparse)
264  return BM_file_write_sparse(fp, map);
265 
266  c = BM_MAGIC;
267  fwrite(&c, sizeof(char), sizeof(char), fp);
268 
269  fwrite(BM_TEXT, BM_TEXT_LEN, sizeof(char), fp);
270 
271  c = BM_FLAT;
272  fwrite(&c, sizeof(char), sizeof(char), fp);
273 
274  fwrite(&(map->rows), sizeof(map->rows), sizeof(char), fp);
275 
276  fwrite(&(map->cols), sizeof(map->cols), sizeof(char), fp);
277 
278  for (i = 0; i < map->rows; i++)
279  if (map->bytes !=
280  fwrite(&(map->data[i * map->bytes]), sizeof(char), map->bytes, fp))
281  return -1;
282  fflush(fp);
283 
284  return 0;
285 }
286 
287 /*!
288  * \brief
289  *
290  * Create map structure and load it from file
291  *
292  * 'fp' should previously been created by <b>BM_file_write()</b>
293  *
294  * Returns struct BM * or NULL on error
295  *
296  * \param fp
297  * \return struct BM
298  */
299 struct BM *BM_file_read(FILE *fp)
300 {
301  struct BM *map;
302  char c;
303  char buf[BM_TEXT_LEN + 1];
304  int i, y, n;
305  struct BMlink *p = NULL, *p2;
306  int cnt;
307 
308  if (NULL == (map = (struct BM *)malloc(sizeof(struct BM))))
309  return (NULL);
310 
311  if (fread(&c, sizeof(char), sizeof(char), fp) != sizeof(char)) {
312  free(map);
313  return NULL;
314  }
315 
316  if (c != BM_MAGIC) {
317  free(map);
318  return NULL;
319  }
320 
321  if (fread(buf, BM_TEXT_LEN, sizeof(char), fp) != sizeof(char)) {
322  free(map);
323  return NULL;
324  }
325 
326  if (fread(&c, sizeof(char), sizeof(char), fp) != sizeof(char)) {
327  free(map);
328  return NULL;
329  }
330  map->sparse = c;
331 
332  if (fread(&(map->rows), sizeof(map->rows), sizeof(char), fp) !=
333  sizeof(char)) {
334  free(map);
335  return NULL;
336  }
337 
338  if (fread(&(map->cols), sizeof(map->cols), sizeof(char), fp) !=
339  sizeof(char)) {
340  free(map);
341  return NULL;
342  }
343 
344  map->bytes = (map->cols + 7) / 8;
345 
346  if (map->sparse == BM_SPARSE)
347  goto readsparse;
348 
349  if (NULL == (map->data = (unsigned char *)malloc(map->bytes * map->rows))) {
350  free(map);
351  return (NULL);
352  }
353 
354  for (i = 0; i < map->rows; i++)
355  if (map->bytes !=
356  fread(&(map->data[i * map->bytes]), sizeof(char), map->bytes, fp)) {
357  free(map->data);
358  free(map);
359  return NULL;
360  }
361 
362  return map;
363 
364 readsparse:
365 
366  link_set_chunk_size(500);
367  map->token = link_init(sizeof(struct BMlink));
368 
369  if (NULL == (map->data = (unsigned char *)malloc(sizeof(struct BMlink *) *
370  map->rows))) {
371  free(map);
372  return (NULL);
373  }
374 
375  for (y = 0; y < map->rows; y++) {
376  /* first get number of links */
377  if (fread(&i, sizeof(i), sizeof(char), fp) != sizeof(char)) {
378  free(map->data);
379  free(map);
380  return NULL;
381  }
382  cnt = i;
383 
384  /* then read them in */
385  for (i = 0; i < cnt; i++) {
386  p2 = (struct BMlink *)link_new(map->token);
387 
388  if (i == 0) {
389  ((struct BMlink **)(map->data))[y] = p2;
390  p = p2;
391  }
392  else {
393  p->next = p2;
394  p = p2;
395  }
396 
397  if (fread(&n, sizeof(n), sizeof(char), fp) != sizeof(char)) {
398  free(map->data);
399  free(map);
400  return NULL;
401  }
402  p->count = n;
403 
404  if (fread(&n, sizeof(n), sizeof(char), fp) != sizeof(char)) {
405  free(map->data);
406  free(map);
407  return NULL;
408  }
409  p->val = n;
410  p->next = NULL;
411  }
412  }
413 
414  return map;
415 }
struct BM * BM_create(int x, int y)
Create bitmap of dimension x/y and return structure token.
Definition: bitmap.c:57
int BM_set(struct BM *map, int x, int y, int val)
Sets bitmap value to 'val' at location 'x' 'y'.
Definition: bitmap.c:182
int BM_file_write(FILE *fp, struct BM *map)
Write bitmap out to file.
Definition: bitmap.c:258
size_t BM_get_map_size(struct BM *map)
Returns size in bytes that bitmap is taking up.
Definition: bitmap.c:236
int BM_get(struct BM *map, int x, int y)
Gets 'val' from the bitmap.
Definition: bitmap.c:213
int BM_destroy(struct BM *map)
Destroy bitmap and free all associated memory.
Definition: bitmap.c:88
struct BM * BM_file_read(FILE *fp)
Create map structure and load it from file.
Definition: bitmap.c:299
#define BM_col_to_bit(x)
Definition: bitmap.c:41
int BM_set_mode(int mode, int size)
Specify the type of data structure to use for bitmap. 'mode' can be either BM_FLAT or BM_SPARSE:
Definition: bitmap.c:145
#define BM_col_to_byte(x)
Definition: bitmap.c:40
#define BM_TEXT
Definition: bitmap.h:6
#define BM_FLAT
Definition: bitmap.h:9
#define BM_TEXT_LEN
Definition: bitmap.h:7
#define BM_SPARSE
Definition: bitmap.h:11
#define BM_MAGIC
Definition: bitmap.h:4
#define NULL
Definition: ccmath.h:32
struct BM * BM_create_sparse(int, int)
Create a sparse bitmap of dimension 'x'/'y'.
Definition: sparse.c:41
int BM_set_sparse(struct BM *, int, int, int)
Set sparse bitmap value to 'val' at location 'x'/'y'.
Definition: sparse.c:122
size_t BM_get_map_size_sparse(struct BM *)
Returns size of sparse bitmap in bytes.
Definition: sparse.c:260
int BM_file_write_sparse(FILE *, struct BM *)
Write sparse bitmap matrix out to disk file 'fp'. NOTE: 'fp' must already be opened and later closed ...
Definition: sparse.c:346
int BM_get_sparse(struct BM *, int, int)
Returns sparse bitmap value at location 'x'/'y'.
Definition: sparse.c:236
int BM_destroy_sparse(struct BM *)
Destroy sparse bitmap and free all associated memory.
Definition: sparse.c:86
struct link_head * link_init(int)
Definition: linkm/init.c:42
void link_set_chunk_size(int)
Definition: linkm/init.c:32
VOID_T * link_new(struct link_head *)
Definition: new.c:12
void * malloc(unsigned)
void free(void *)
Definition: bitmap.h:17
int rows
Definition: bitmap.h:18
struct link_head * token
Definition: bitmap.h:24
int cols
Definition: bitmap.h:19
unsigned char * data
Definition: bitmap.h:21
size_t bytes
Definition: bitmap.h:20
int sparse
Definition: bitmap.h:22
#define x