Back to index

tetex-bin  3.0
wbmp.c
Go to the documentation of this file.
00001 
00002 /* WBMP
00003    ** ----
00004    ** WBMP Level 0: B/W, Uncompressed
00005    ** This implements the WBMP format as specified in WAPSpec 1.1 and 1.2.
00006    ** It does not support ExtHeaders as defined in the spec. The spec states
00007    ** that a WAP client does not need to implement ExtHeaders.
00008    **
00009    ** (c) 2000 Johan Van den Brande <johan@vandenbrande.com>
00010  */
00011 
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #endif
00015 
00016 #include <stdio.h>
00017 #include <stddef.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 
00021 #include "wbmp.h"
00022 #include "gd.h"
00023 #include "gdhelpers.h"
00024 
00025 #ifdef NOTDEF
00026 #define __TEST                     /* Compile with main function */
00027 #define __DEBUG                    /* Extra verbose when with __TEST */
00028 #define __WRITE                    /* readwbmp and writewbmp(stdout) */
00029 #define __VIEW                     /* view the wbmp on stdout */
00030 #endif
00031 
00032 /* getmbi
00033    ** ------
00034    ** Get a multibyte integer from a generic getin function 
00035    ** 'getin' can be getc, with in = NULL
00036    ** you can find getin as a function just above the main function
00037    ** This way you gain a lot of flexibilty about how this package
00038    ** reads a wbmp file.
00039  */
00040 int
00041 getmbi (int (*getin) (void *in), void *in)
00042 {
00043   int i, mbi = 0;
00044 
00045   do
00046     {
00047       i = getin (in);
00048       if (i < 0)
00049        return (-1);
00050       mbi = (mbi << 7) | (i & 0x7f);
00051     }
00052   while (i & 0x80);
00053 
00054   return (mbi);
00055 }
00056 
00057 
00058 /* putmbi
00059    ** ------
00060    ** Put a multibyte intgerer in some kind of output stream
00061    ** I work here with a function pointer, to make it as generic
00062    ** as possible. Look at this function as an iterator on the
00063    ** mbi integers it spits out.
00064    **
00065  */
00066 void
00067 putmbi (int i, void (*putout) (int c, void *out), void *out)
00068 {
00069   int cnt, l, accu;
00070 
00071   /* Get number of septets */
00072   cnt = 0;
00073   accu = 0;
00074   while (accu != i)
00075     accu += i & 0x7f << 7 * cnt++;
00076 
00077   /* Produce the multibyte output */
00078   for (l = cnt - 1; l > 0; l--)
00079     putout (0x80 | (i & 0x7f << 7 * l) >> 7 * l, out);
00080 
00081   putout (i & 0x7f, out);
00082 
00083 }
00084 
00085 
00086 
00087 /* skipheader
00088    ** ----------
00089    ** Skips the ExtHeader. Not needed for the moment
00090    **
00091  */
00092 int
00093 skipheader (int (*getin) (void *in), void *in)
00094 {
00095   int i;
00096 
00097   do
00098     {
00099       i = getin (in);
00100       if (i < 0)
00101        return (-1);
00102     }
00103   while (i & 0x80);
00104 
00105   return (0);
00106 }
00107 
00108 /* create wbmp
00109    ** -----------
00110    ** create an empty wbmp
00111    **
00112  */
00113 Wbmp *
00114 createwbmp (int width, int height, int color)
00115 {
00116   int i;
00117 
00118   Wbmp *wbmp;
00119   if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
00120     return (NULL);
00121 
00122   if (overflow2(sizeof (int), width)) {
00123     gdFree(wbmp);
00124     return NULL;
00125   }
00126   if (overflow2(sizeof (int) * width, height)) {
00127     gdFree(wbmp);
00128     return NULL;
00129   }
00130   if ((wbmp->bitmap =
00131        (int *) gdMalloc (sizeof (int) * width * height)) == NULL)
00132     {
00133       gdFree (wbmp);
00134       return (NULL);
00135     }
00136 
00137   wbmp->width = width;
00138   wbmp->height = height;
00139 
00140   for (i = 0; i < width * height; wbmp->bitmap[i++] = color);
00141 
00142   return (wbmp);
00143 }
00144 
00145 
00146 
00147 /* readwbmp
00148    ** -------
00149    ** Actually reads the WBMP format from an open file descriptor
00150    ** It goes along by returning a pointer to a WBMP struct.
00151    **
00152  */
00153 int
00154 readwbmp (int (*getin) (void *in), void *in, Wbmp ** return_wbmp)
00155 {
00156   int row, col, byte, pel, pos;
00157   Wbmp *wbmp;
00158 
00159   if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
00160     return (-1);
00161 
00162   wbmp->type = getin (in);
00163   if (wbmp->type != 0)
00164     {
00165       gdFree (wbmp);
00166       return (-1);
00167     }
00168 
00169   if (skipheader (getin, in))
00170     return (-1);
00171 
00172 
00173   wbmp->width = getmbi (getin, in);
00174   if (wbmp->width == -1)
00175     {
00176       gdFree (wbmp);
00177       return (-1);
00178     }
00179 
00180   wbmp->height = getmbi (getin, in);
00181   if (wbmp->height == -1)
00182     {
00183       gdFree (wbmp);
00184       return (-1);
00185     }
00186 
00187 #ifdef __DEBUG
00188   printf ("W: %d, H: %d\n", wbmp->width, wbmp->height);
00189 #endif
00190 
00191   if (overflow2(sizeof (int), wbmp->width) ||
00192     overflow2(sizeof (int) * wbmp->width, wbmp->height))
00193     {
00194       gdFree(wbmp);
00195       return (-1);
00196     }
00197   if ((wbmp->bitmap =
00198        (int *) gdMalloc (sizeof (int) * wbmp->width * wbmp->height)) == NULL)
00199     {
00200       gdFree (wbmp);
00201       return (-1);
00202     }
00203 
00204 #ifdef __DEBUG
00205   printf ("DATA CONSTRUCTED\n");
00206 #endif
00207 
00208   pos = 0;
00209   for (row = 0; row < wbmp->height; row++)
00210     {
00211       for (col = 0; col < wbmp->width;)
00212        {
00213          byte = getin (in);
00214 
00215          for (pel = 7; pel >= 0; pel--)
00216            {
00217              if (col++ < wbmp->width)
00218               {
00219                 if (byte & 1 << pel)
00220                   {
00221                     wbmp->bitmap[pos] = WBMP_WHITE;
00222                   }
00223                 else
00224                   {
00225                     wbmp->bitmap[pos] = WBMP_BLACK;
00226                   }
00227                 pos++;
00228               }
00229            }
00230        }
00231     }
00232 
00233   *return_wbmp = wbmp;
00234 
00235   return (0);
00236 }
00237 
00238 
00239 /* writewbmp
00240    ** ---------
00241    ** Write a wbmp to a file descriptor
00242    **
00243    ** Why not just giving a filedescriptor to this function?
00244    ** Well, the incentive to write this function was the complete
00245    ** integration in gd library from www.boutell.com. They use
00246    ** their own io functions, so the passing of a function seemed to be 
00247    ** a logic(?) decision ...
00248    **
00249  */
00250 int
00251 writewbmp (Wbmp * wbmp, void (*putout) (int c, void *out), void *out)
00252 {
00253   int row, col;
00254   int bitpos, octet;
00255 
00256   /* Generate the header */
00257   putout (0, out);          /* WBMP Type 0: B/W, Uncompressed bitmap */
00258   putout (0, out);          /* FixHeaderField */
00259 
00260 
00261 
00262   /* Size of the image */
00263   putmbi (wbmp->width, putout, out);      /* width */
00264   putmbi (wbmp->height, putout, out);     /* height */
00265 
00266 
00267   /* Image data */
00268   for (row = 0; row < wbmp->height; row++)
00269     {
00270       bitpos = 8;
00271       octet = 0;
00272       for (col = 0; col < wbmp->width; col++)
00273        {
00274          octet |=
00275            ((wbmp->bitmap[row * wbmp->width + col] ==
00276              1) ? WBMP_WHITE : WBMP_BLACK) << --bitpos;
00277          if (bitpos == 0)
00278            {
00279              bitpos = 8;
00280              putout (octet, out);
00281              octet = 0;
00282            }
00283        }
00284       if (bitpos != 8)
00285        putout (octet, out);
00286 
00287     }
00288   return (0);
00289 
00290 }
00291 
00292 
00293 /* freewbmp
00294    ** --------
00295    ** gdFrees up memory occupied by a WBMP structure
00296    **
00297  */
00298 void
00299 freewbmp (Wbmp * wbmp)
00300 {
00301   gdFree (wbmp->bitmap);
00302   gdFree (wbmp);
00303 }
00304 
00305 
00306 /* printwbmp
00307    ** ---------
00308    ** print a WBMP to stdout for visualisation
00309    **
00310  */
00311 void
00312 printwbmp (Wbmp * wbmp)
00313 {
00314   int row, col;
00315   for (row = 0; row < wbmp->height; row++)
00316     {
00317       for (col = 0; col < wbmp->width; col++)
00318        {
00319          if (wbmp->bitmap[wbmp->width * row + col] == WBMP_BLACK)
00320            {
00321              putchar ('#');
00322            }
00323          else
00324            {
00325              putchar (' ');
00326            }
00327        }
00328       putchar ('\n');
00329     }
00330 }
00331 
00332 #ifdef __TEST
00333 
00334 /* putout to file descriptor
00335    ** -------------------------
00336  */
00337 int
00338 putout (int c, void *out)
00339 {
00340   return (putc (c, (FILE *) out));
00341 }
00342 
00343 /* getin from file descriptor 
00344    ** --------------------------
00345  */
00346 int
00347 getin (void *in)
00348 {
00349   return (getc ((FILE *) in));
00350 }
00351 
00352 
00353 /* Main function
00354    ** -------------
00355    **
00356  */
00357 int
00358 main (int argc, char *argv[])
00359 {
00360   FILE *wbmp_file;
00361   Wbmp *wbmp;
00362 
00363   wbmp_file = fopen (argv[1], "rb");
00364   if (wbmp_file)
00365     {
00366       readwbmp (&getin, wbmp_file, &wbmp);
00367 
00368 #ifdef __VIEW
00369 
00370 #ifdef __DEBUG
00371       printf ("\nVIEWING IMAGE\n");
00372 #endif
00373 
00374       printwbmp (wbmp);
00375 #endif
00376 
00377 #ifdef __WRITE
00378 
00379 #ifdef __DEBUG
00380       printf ("\nDUMPING WBMP to STDOUT\n");
00381 #endif
00382 
00383       writewbmp (wbmp, &putout, stdout);
00384 #endif
00385 
00386       freewbmp (wbmp);
00387       fclose (wbmp_file);
00388     }
00389 }
00390 #endif