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