wbmp.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /* WBMP
  2. ** ----
  3. ** WBMP Level 0: B/W, Uncompressed
  4. ** This implements the WBMP format as specified in WAPSpec 1.1 and 1.2.
  5. ** It does not support ExtHeaders as defined in the spec. The spec states
  6. ** that a WAP client does not need to implement ExtHeaders.
  7. **
  8. ** (c) 2000 Johan Van den Brande <johan@vandenbrande.com>
  9. */
  10. #include <stdio.h>
  11. #include <stddef.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "wbmp.h"
  15. #include "gd.h"
  16. #include "gdhelpers.h"
  17. #ifdef NOTDEF
  18. #define __TEST /* Compile with main function */
  19. #define __DEBUG /* Extra verbose when with __TEST */
  20. #define __WRITE /* readwbmp and writewbmp(stdout) */
  21. #define __VIEW /* view the wbmp on stdout */
  22. #endif
  23. /* getmbi
  24. ** ------
  25. ** Get a multibyte integer from a generic getin function
  26. ** 'getin' can be getc, with in = NULL
  27. ** you can find getin as a function just above the main function
  28. ** This way you gain a lot of flexibilty about how this package
  29. ** reads a wbmp file.
  30. */
  31. int
  32. getmbi (int (*getin) (void *in), void *in)
  33. {
  34. int i, mbi = 0;
  35. do
  36. {
  37. i = getin (in);
  38. if (i < 0)
  39. return (-1);
  40. mbi = (mbi << 7) | (i & 0x7f);
  41. }
  42. while (i & 0x80);
  43. return (mbi);
  44. }
  45. /* putmbi
  46. ** ------
  47. ** Put a multibyte intgerer in some kind of output stream
  48. ** I work here with a function pointer, to make it as generic
  49. ** as possible. Look at this function as an iterator on the
  50. ** mbi integers it spits out.
  51. **
  52. */
  53. void
  54. putmbi (int i, void (*putout) (int c, void *out), void *out)
  55. {
  56. int cnt, l, accu;
  57. /* Get number of septets */
  58. cnt = 0;
  59. accu = 0;
  60. while (accu != i)
  61. accu += i & 0x7f << 7 * cnt++;
  62. /* Produce the multibyte output */
  63. for (l = cnt - 1; l > 0; l--)
  64. putout (0x80 | (i & 0x7f << 7 * l) >> 7 * l, out);
  65. putout (i & 0x7f, out);
  66. }
  67. /* skipheader
  68. ** ----------
  69. ** Skips the ExtHeader. Not needed for the moment
  70. **
  71. */
  72. int
  73. skipheader (int (*getin) (void *in), void *in)
  74. {
  75. int i;
  76. do
  77. {
  78. i = getin (in);
  79. if (i < 0)
  80. return (-1);
  81. }
  82. while (i & 0x80);
  83. return (0);
  84. }
  85. /* create wbmp
  86. ** -----------
  87. ** create an empty wbmp
  88. **
  89. */
  90. Wbmp *
  91. createwbmp (int width, int height, int color)
  92. {
  93. int i;
  94. Wbmp *wbmp;
  95. if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
  96. return (NULL);
  97. if (overflow2(sizeof (int), width)) {
  98. gdFree(wbmp);
  99. return NULL;
  100. }
  101. if (overflow2(sizeof (int) * width, height)) {
  102. gdFree(wbmp);
  103. return NULL;
  104. }
  105. if ((wbmp->bitmap = (int *) safe_emalloc(sizeof(int), width * height, 0)) == NULL)
  106. {
  107. gdFree (wbmp);
  108. return (NULL);
  109. }
  110. wbmp->width = width;
  111. wbmp->height = height;
  112. for (i = 0; i < width * height; wbmp->bitmap[i++] = color);
  113. return (wbmp);
  114. }
  115. /* readwbmp
  116. ** -------
  117. ** Actually reads the WBMP format from an open file descriptor
  118. ** It goes along by returning a pointer to a WBMP struct.
  119. **
  120. */
  121. int
  122. readwbmp (int (*getin) (void *in), void *in, Wbmp ** return_wbmp)
  123. {
  124. int row, col, byte, pel, pos;
  125. Wbmp *wbmp;
  126. if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
  127. return (-1);
  128. wbmp->type = getin (in);
  129. if (wbmp->type != 0)
  130. {
  131. gdFree (wbmp);
  132. return (-1);
  133. }
  134. if (skipheader (getin, in))
  135. {
  136. gdFree (wbmp);
  137. return (-1);
  138. }
  139. wbmp->width = getmbi (getin, in);
  140. if (wbmp->width == -1)
  141. {
  142. gdFree (wbmp);
  143. return (-1);
  144. }
  145. wbmp->height = getmbi (getin, in);
  146. if (wbmp->height == -1)
  147. {
  148. gdFree (wbmp);
  149. return (-1);
  150. }
  151. #ifdef __DEBUG
  152. printf ("W: %d, H: %d\n", wbmp->width, wbmp->height);
  153. #endif
  154. if (overflow2(sizeof (int), wbmp->width) ||
  155. overflow2(sizeof (int) * wbmp->width, wbmp->height))
  156. {
  157. gdFree(wbmp);
  158. return (-1);
  159. }
  160. if ((wbmp->bitmap = (int *) safe_emalloc((size_t)wbmp->width * wbmp->height, sizeof(int), 0)) == NULL)
  161. {
  162. gdFree (wbmp);
  163. return (-1);
  164. }
  165. #ifdef __DEBUG
  166. printf ("DATA CONSTRUCTED\n");
  167. #endif
  168. pos = 0;
  169. for (row = 0; row < wbmp->height; row++)
  170. {
  171. for (col = 0; col < wbmp->width;)
  172. {
  173. byte = getin (in);
  174. for (pel = 7; pel >= 0; pel--)
  175. {
  176. if (col++ < wbmp->width)
  177. {
  178. if (byte & 1 << pel)
  179. {
  180. wbmp->bitmap[pos] = WBMP_WHITE;
  181. }
  182. else
  183. {
  184. wbmp->bitmap[pos] = WBMP_BLACK;
  185. }
  186. pos++;
  187. }
  188. }
  189. }
  190. }
  191. *return_wbmp = wbmp;
  192. return (0);
  193. }
  194. /* writewbmp
  195. ** ---------
  196. ** Write a wbmp to a file descriptor
  197. **
  198. ** Why not just giving a filedescriptor to this function?
  199. ** Well, the incentive to write this function was the complete
  200. ** integration in gd library from www.boutell.com. They use
  201. ** their own io functions, so the passing of a function seemed to be
  202. ** a logic(?) decision ...
  203. **
  204. */
  205. int
  206. writewbmp (Wbmp * wbmp, void (*putout) (int c, void *out), void *out)
  207. {
  208. int row, col;
  209. int bitpos, octet;
  210. /* Generate the header */
  211. putout (0, out); /* WBMP Type 0: B/W, Uncompressed bitmap */
  212. putout (0, out); /* FixHeaderField */
  213. /* Size of the image */
  214. putmbi (wbmp->width, putout, out); /* width */
  215. putmbi (wbmp->height, putout, out); /* height */
  216. /* Image data */
  217. for (row = 0; row < wbmp->height; row++)
  218. {
  219. bitpos = 8;
  220. octet = 0;
  221. for (col = 0; col < wbmp->width; col++)
  222. {
  223. octet |= ((wbmp->bitmap[row * wbmp->width + col] == 1) ? WBMP_WHITE : WBMP_BLACK) << --bitpos;
  224. if (bitpos == 0)
  225. {
  226. bitpos = 8;
  227. putout (octet, out);
  228. octet = 0;
  229. }
  230. }
  231. if (bitpos != 8)
  232. putout (octet, out);
  233. }
  234. return (0);
  235. }
  236. /* freewbmp
  237. ** --------
  238. ** gdFrees up memory occupied by a WBMP structure
  239. **
  240. */
  241. void
  242. freewbmp (Wbmp * wbmp)
  243. {
  244. gdFree (wbmp->bitmap);
  245. gdFree (wbmp);
  246. }
  247. /* printwbmp
  248. ** ---------
  249. ** print a WBMP to stdout for visualisation
  250. **
  251. */
  252. void
  253. printwbmp (Wbmp * wbmp)
  254. {
  255. int row, col;
  256. for (row = 0; row < wbmp->height; row++)
  257. {
  258. for (col = 0; col < wbmp->width; col++)
  259. {
  260. if (wbmp->bitmap[wbmp->width * row + col] == WBMP_BLACK)
  261. {
  262. putchar ('#');
  263. }
  264. else
  265. {
  266. putchar (' ');
  267. }
  268. }
  269. putchar ('\n');
  270. }
  271. }
  272. #ifdef __TEST
  273. /* putout to file descriptor
  274. ** -------------------------
  275. */
  276. int
  277. putout (int c, void *out)
  278. {
  279. return (putc (c, (FILE *) out));
  280. }
  281. /* getin from file descriptor
  282. ** --------------------------
  283. */
  284. int
  285. getin (void *in)
  286. {
  287. return (getc ((FILE *) in));
  288. }
  289. /* Main function
  290. ** -------------
  291. **
  292. */
  293. int
  294. main (int argc, char *argv[])
  295. {
  296. FILE *wbmp_file;
  297. Wbmp *wbmp;
  298. wbmp_file = fopen (argv[1], "rb");
  299. if (wbmp_file)
  300. {
  301. readwbmp (&getin, wbmp_file, &wbmp);
  302. #ifdef __VIEW
  303. #ifdef __DEBUG
  304. printf ("\nVIEWING IMAGE\n");
  305. #endif
  306. printwbmp (wbmp);
  307. #endif
  308. #ifdef __WRITE
  309. #ifdef __DEBUG
  310. printf ("\nDUMPING WBMP to STDOUT\n");
  311. #endif
  312. writewbmp (wbmp, &putout, stdout);
  313. #endif
  314. freewbmp (wbmp);
  315. fclose (wbmp_file);
  316. }
  317. }
  318. #endif