GRASS Programmer's Manual  6.4.2(2012)
bitmap.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines