GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
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
43static int Mode = BM_FLAT;
44static 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 */
57struct 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 */
88int 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 */
145int 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 */
182int 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 */
213int 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 */
236size_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 */
258int 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 */
299struct 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
365
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
#define BM_col_to_bit(x)
Definition bitmap.c:41
struct BM * BM_file_read(FILE *fp)
Create map structure and load it from file.
Definition bitmap.c:299
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
int BM_set_sparse(struct BM *, int, int, int)
Set sparse bitmap value to 'val' at location 'x'/'y'.
Definition sparse.c:122
struct BM * BM_create_sparse(int, int)
Create a sparse bitmap of dimension 'x'/'y'.
Definition sparse.c:41
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
VOID_T * link_new(struct link_head *)
Definition new.c:12
void link_set_chunk_size(int)
Definition linkm/init.c:32
struct link_head * link_init(int)
Definition linkm/init.c:42
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