GRASS Programmer's Manual
6.4.2(2012)
|
00001 /* 00002 ** Bitmap library 00003 ** 00004 ** Written by David Gerdes 12 November 1992 00005 ** US Army Construction Engineering Research Laboratories 00006 ** 00007 ** 00008 ** This library provides basic support for the creation and manipulation 00009 ** of two dimensional bitmap arrays. 00010 ** 00011 ** struct BM * 00012 ** BM_create (x, y) Create bitmap of specified dimensions 00013 ** 00014 ** BM_set_mode (mode, size) Specify Mode and data size in bits. 00015 ** Affects all further calls to BM_create() 00016 ** Mode can be BM_FLAT or BM_SPARSE 00017 ** Size can only be 1 currently. 00018 ** 00019 ** BM_destroy (map) Destroy bitmap and free memory 00020 ** 00021 ** BM_set (map, x, y, val) Set array position to val [TRUE/FALSE] 00022 ** 00023 ** BM_get (map, x, y) Return value at array position 00024 ** 00025 ** 00026 ** BM_file_write (fp, map) Write bitmap to file 00027 ** 00028 ** struct BM * 00029 ** BM_file_read (fp) Create bitmap and load from file 00030 ** 00031 ** BM_get_map_size (map) returns size in bytes that bitmap is 00032 ** taking up. For diagnosis use. 00033 */ 00034 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 #include <grass/linkm.h> 00038 #include <grass/bitmap.h> 00039 00040 00041 #define BM_col_to_byte(x) ((x)/8) 00042 #define BM_col_to_bit(x) ((x)%8) 00043 00044 static int Mode = BM_FLAT; 00045 static int Size = 1; 00046 00047 00060 struct BM *BM_create(int x, int y) 00061 { 00062 struct BM *map; 00063 00064 if (Mode == BM_SPARSE) 00065 return BM_create_sparse(x, y); 00066 00067 if (NULL == (map = (struct BM *)malloc(sizeof(struct BM)))) 00068 return (NULL); 00069 00070 map->bytes = (x + 7) / 8; 00071 00072 if (NULL == 00073 (map->data = (unsigned char *)calloc(map->bytes * y, sizeof(char)))) 00074 return (NULL); 00075 00076 map->rows = y; 00077 map->cols = x; 00078 map->sparse = 0; 00079 00080 return map; 00081 } 00082 00083 00090 int BM_destroy(struct BM *map) 00091 { 00092 if (map->sparse) 00093 return BM_destroy_sparse(map); 00094 00095 free(map->data); 00096 free(map); 00097 00098 return 0; 00099 } 00100 00101 00102 /* 00103 ** Caller can specify type of data structure to use for bitmap, as 00104 ** well as the size of the data values. Currently since this is 00105 ** the 'bitmap' library, size can ONLY have value 1. 00106 ** Size is number of bits of storage per cell. 00107 ** 00108 ** Mode: 00109 ** BM_FLAT Your basic packed bitmap, eight values are stored per byte 00110 ** Thus you get a 1:8 compression over using char arrays 00111 ** and a 1:32 compression over using CELL arrays. 00112 ** 00113 ** 00114 ** BM_SPARSE Linked array of values. Much more efficient for large 00115 ** very sparse arrays. Slower access, especially for writing, 00116 ** but can save several orders of magnitude of memory on large 00117 ** bitmaps since size of FLAT bitmap is O(M*N) 00118 ** 00119 ** 00120 ** Returns 0 or negative on error; 00121 ** If error it will print a warning message to stderr and continue 00122 ** continue by running but will not change the option in error. 00123 */ 00124 00149 int BM_set_mode(int mode, int size) 00150 { 00151 int ret = 0; 00152 00153 switch (mode) { 00154 case BM_FLAT: 00155 case BM_SPARSE: 00156 Mode = mode; 00157 default: 00158 fprintf(stderr, "BM_set_mode: Unknown mode: %d\n", mode); 00159 ret--; 00160 } 00161 00162 if (size != 1) { 00163 fprintf(stderr, "BM_set_mode: Bad size: %d\n", size); 00164 ret--; 00165 } 00166 else 00167 Size = size; 00168 00169 return ret; 00170 } 00171 00172 00187 int BM_set(struct BM *map, int x, int y, int val) 00188 { 00189 unsigned char byte; 00190 00191 if (x < 0 || x >= map->cols || y < 0 || y >= map->rows) 00192 return 0; 00193 00194 if (map->sparse) 00195 return BM_set_sparse(map, x, y, val); 00196 00197 byte = 0x01 << BM_col_to_bit(x); 00198 if (val) 00199 map->data[BM_col_to_byte(x) + y * map->bytes] |= byte; 00200 else 00201 map->data[BM_col_to_byte(x) + y * map->bytes] &= ~byte; 00202 00203 return 0; 00204 } 00205 00206 00220 int BM_get(struct BM *map, int x, int y) 00221 { 00222 unsigned char byte; 00223 00224 if (x < 0 || x >= map->cols || y < 0 || y >= map->rows) 00225 return -1; 00226 00227 if (map->sparse) 00228 return BM_get_sparse(map, x, y); 00229 00230 byte = map->data[BM_col_to_byte(x) + y * map->bytes]; 00231 00232 return byte >> BM_col_to_bit(x) & 0x01; 00233 } 00234 00235 00245 int BM_get_map_size(struct BM *map) 00246 { 00247 if (map->sparse) 00248 return BM_get_map_size_sparse(map); 00249 00250 return map->bytes * map->rows; 00251 } 00252 00253 00269 int BM_file_write(FILE * fp, struct BM *map) 00270 { 00271 char c; 00272 int i; 00273 00274 if (map->sparse) 00275 return BM_file_write_sparse(fp, map); 00276 00277 c = BM_MAGIC; 00278 fwrite(&c, sizeof(char), sizeof(char), fp); 00279 00280 fwrite(BM_TEXT, BM_TEXT_LEN, sizeof(char), fp); 00281 00282 c = BM_FLAT; 00283 fwrite(&c, sizeof(char), sizeof(char), fp); 00284 00285 fwrite(&(map->rows), sizeof(map->rows), sizeof(char), fp); 00286 00287 fwrite(&(map->cols), sizeof(map->cols), sizeof(char), fp); 00288 00289 for (i = 0; i < map->rows; i++) 00290 if (map->bytes != 00291 fwrite(&(map->data[i * map->bytes]), sizeof(char), map->bytes, 00292 fp)) 00293 return -1; 00294 fflush(fp); 00295 00296 return 0; 00297 } 00298 00299 00313 struct BM *BM_file_read(FILE * fp) 00314 { 00315 struct BM *map; 00316 char c; 00317 char buf[BM_TEXT_LEN + 1]; 00318 int i, y, n; 00319 struct BMlink *p = NULL, *p2; 00320 int cnt; 00321 00322 if (NULL == (map = (struct BM *)malloc(sizeof(struct BM)))) 00323 return (NULL); 00324 00325 fread(&c, sizeof(char), sizeof(char), fp); 00326 if (c != BM_MAGIC) 00327 return NULL; 00328 00329 fread(buf, BM_TEXT_LEN, sizeof(char), fp); 00330 00331 fread(&c, sizeof(char), sizeof(char), fp); 00332 map->sparse = c; 00333 00334 00335 fread(&(map->rows), sizeof(map->rows), sizeof(char), fp); 00336 00337 fread(&(map->cols), sizeof(map->cols), sizeof(char), fp); 00338 00339 map->bytes = (map->cols + 7) / 8; 00340 00341 if (map->sparse == BM_SPARSE) 00342 goto readsparse; 00343 00344 if (NULL == (map->data = (unsigned char *)malloc(map->bytes * map->rows))) 00345 return (NULL); 00346 00347 00348 for (i = 0; i < map->rows; i++) 00349 if (map->bytes != 00350 fread(&(map->data[i * map->bytes]), sizeof(char), map->bytes, fp)) 00351 return NULL; 00352 00353 00354 return map; 00355 00356 readsparse: 00357 00358 link_set_chunk_size(500); 00359 map->token = link_init(sizeof(struct BMlink)); 00360 00361 00362 if (NULL == (map->data = (unsigned char *) 00363 malloc(sizeof(struct BMlink *) * map->rows))) 00364 return (NULL); 00365 00366 for (y = 0; y < map->rows; y++) { 00367 /* first get number of links */ 00368 fread(&i, sizeof(i), sizeof(char), fp); 00369 cnt = i; 00370 00371 00372 /* then read them in */ 00373 for (i = 0; i < cnt; i++) { 00374 p2 = (struct BMlink *)link_new(map->token); 00375 00376 if (i == 0) { 00377 ((struct BMlink **)(map->data))[y] = p2; 00378 p = p2; 00379 } 00380 else { 00381 p->next = p2; 00382 p = p2; 00383 } 00384 00385 fread(&n, sizeof(n), sizeof(char), fp); 00386 p->count = n; 00387 00388 fread(&n, sizeof(n), sizeof(char), fp); 00389 p->val = n; 00390 p->next = NULL; 00391 } 00392 } 00393 00394 return map; 00395 }