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
38 : getmbi (int (*getin) (void *in), void *in)
39 7 : {
40 7 : int i, mbi = 0;
41 :
42 : do
43 : {
44 11 : i = getin (in);
45 11 : if (i < 0)
46 0 : return (-1);
47 11 : mbi = (mbi << 7) | (i & 0x7f);
48 : }
49 11 : while (i & 0x80);
50 :
51 7 : 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
64 : putmbi (int i, void (*putout) (int c, void *out), void *out)
65 2 : {
66 : int cnt, l, accu;
67 :
68 : /* Get number of septets */
69 2 : cnt = 0;
70 2 : accu = 0;
71 6 : while (accu != i)
72 2 : accu += i & 0x7f << 7 * cnt++;
73 :
74 : /* Produce the multibyte output */
75 2 : for (l = cnt - 1; l > 0; l--)
76 0 : putout (0x80 | (i & 0x7f << 7 * l) >> 7 * l, out);
77 :
78 2 : putout (i & 0x7f, out);
79 :
80 2 : }
81 :
82 :
83 :
84 : /* skipheader
85 : ** ----------
86 : ** Skips the ExtHeader. Not needed for the moment
87 : **
88 : */
89 : int
90 : skipheader (int (*getin) (void *in), void *in)
91 3 : {
92 : int i;
93 :
94 : do
95 : {
96 3 : i = getin (in);
97 3 : if (i < 0)
98 0 : return (-1);
99 : }
100 3 : while (i & 0x80);
101 :
102 3 : return (0);
103 : }
104 :
105 : /* create wbmp
106 : ** -----------
107 : ** create an empty wbmp
108 : **
109 : */
110 : Wbmp *
111 : createwbmp (int width, int height, int color)
112 1 : {
113 : int i;
114 :
115 : Wbmp *wbmp;
116 1 : if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
117 0 : return (NULL);
118 :
119 1 : if (overflow2(sizeof (int), width)) {
120 0 : gdFree(wbmp);
121 0 : return NULL;
122 : }
123 1 : if (overflow2(sizeof (int) * width, height)) {
124 0 : gdFree(wbmp);
125 0 : return NULL;
126 : }
127 :
128 1 : if ((wbmp->bitmap = (int *) safe_emalloc(sizeof(int), width * height, 0)) == NULL)
129 : {
130 0 : gdFree (wbmp);
131 0 : return (NULL);
132 : }
133 :
134 1 : wbmp->width = width;
135 1 : wbmp->height = height;
136 :
137 1 : for (i = 0; i < width * height; wbmp->bitmap[i++] = color);
138 :
139 1 : 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
151 : readwbmp (int (*getin) (void *in), void *in, Wbmp ** return_wbmp)
152 3 : {
153 : int row, col, byte, pel, pos;
154 : Wbmp *wbmp;
155 :
156 3 : if ((wbmp = (Wbmp *) gdMalloc (sizeof (Wbmp))) == NULL)
157 0 : return (-1);
158 :
159 3 : wbmp->type = getin (in);
160 3 : if (wbmp->type != 0)
161 : {
162 0 : gdFree (wbmp);
163 0 : return (-1);
164 : }
165 :
166 3 : if (skipheader (getin, in))
167 0 : return (-1);
168 :
169 :
170 3 : wbmp->width = getmbi (getin, in);
171 3 : if (wbmp->width == -1)
172 : {
173 0 : gdFree (wbmp);
174 0 : return (-1);
175 : }
176 :
177 3 : wbmp->height = getmbi (getin, in);
178 3 : if (wbmp->height == -1)
179 : {
180 0 : gdFree (wbmp);
181 0 : return (-1);
182 : }
183 :
184 : #ifdef __DEBUG
185 : printf ("W: %d, H: %d\n", wbmp->width, wbmp->height);
186 : #endif
187 :
188 3 : if (overflow2(sizeof (int), wbmp->width) ||
189 : overflow2(sizeof (int) * wbmp->width, wbmp->height))
190 : {
191 1 : gdFree(wbmp);
192 1 : return (-1);
193 : }
194 :
195 2 : if ((wbmp->bitmap = (int *) safe_emalloc((size_t)wbmp->width * wbmp->height, sizeof(int), 0)) == NULL)
196 : {
197 0 : gdFree (wbmp);
198 0 : return (-1);
199 : }
200 :
201 : #ifdef __DEBUG
202 : printf ("DATA CONSTRUCTED\n");
203 : #endif
204 :
205 2 : pos = 0;
206 13 : for (row = 0; row < wbmp->height; row++)
207 : {
208 33 : for (col = 0; col < wbmp->width;)
209 : {
210 11 : byte = getin (in);
211 :
212 99 : for (pel = 7; pel >= 0; pel--)
213 : {
214 88 : if (col++ < wbmp->width)
215 : {
216 61 : if (byte & 1 << pel)
217 : {
218 59 : wbmp->bitmap[pos] = WBMP_WHITE;
219 : }
220 : else
221 : {
222 2 : wbmp->bitmap[pos] = WBMP_BLACK;
223 : }
224 61 : pos++;
225 : }
226 : }
227 : }
228 : }
229 :
230 2 : *return_wbmp = wbmp;
231 :
232 2 : return (0);
233 : }
234 :
235 :
236 : /* writewbmp
237 : ** ---------
238 : ** Write a wbmp to a file descriptor
239 : **
240 : ** Why not just giving a filedescriptor to this function?
241 : ** Well, the incentive to write this function was the complete
242 : ** integration in gd library from www.boutell.com. They use
243 : ** their own io functions, so the passing of a function seemed to be
244 : ** a logic(?) decision ...
245 : **
246 : */
247 : int
248 : writewbmp (Wbmp * wbmp, void (*putout) (int c, void *out), void *out)
249 1 : {
250 : int row, col;
251 : int bitpos, octet;
252 :
253 : /* Generate the header */
254 1 : putout (0, out); /* WBMP Type 0: B/W, Uncompressed bitmap */
255 1 : putout (0, out); /* FixHeaderField */
256 :
257 :
258 :
259 : /* Size of the image */
260 1 : putmbi (wbmp->width, putout, out); /* width */
261 1 : putmbi (wbmp->height, putout, out); /* height */
262 :
263 :
264 : /* Image data */
265 7 : for (row = 0; row < wbmp->height; row++)
266 : {
267 6 : bitpos = 8;
268 6 : octet = 0;
269 42 : for (col = 0; col < wbmp->width; col++)
270 : {
271 36 : octet |= ((wbmp->bitmap[row * wbmp->width + col] == 1) ? WBMP_WHITE : WBMP_BLACK) << --bitpos;
272 36 : if (bitpos == 0)
273 : {
274 0 : bitpos = 8;
275 0 : putout (octet, out);
276 0 : octet = 0;
277 : }
278 : }
279 6 : if (bitpos != 8)
280 6 : putout (octet, out);
281 :
282 : }
283 1 : return (0);
284 :
285 : }
286 :
287 :
288 : /* freewbmp
289 : ** --------
290 : ** gdFrees up memory occupied by a WBMP structure
291 : **
292 : */
293 : void
294 : freewbmp (Wbmp * wbmp)
295 3 : {
296 3 : gdFree (wbmp->bitmap);
297 3 : gdFree (wbmp);
298 3 : }
299 :
300 :
301 : /* printwbmp
302 : ** ---------
303 : ** print a WBMP to stdout for visualisation
304 : **
305 : */
306 : void
307 : printwbmp (Wbmp * wbmp)
308 0 : {
309 : int row, col;
310 0 : for (row = 0; row < wbmp->height; row++)
311 : {
312 0 : for (col = 0; col < wbmp->width; col++)
313 : {
314 0 : if (wbmp->bitmap[wbmp->width * row + col] == WBMP_BLACK)
315 : {
316 0 : putchar ('#');
317 : }
318 : else
319 : {
320 0 : putchar (' ');
321 : }
322 : }
323 0 : putchar ('\n');
324 : }
325 0 : }
326 :
327 : #ifdef __TEST
328 :
329 : /* putout to file descriptor
330 : ** -------------------------
331 : */
332 : int
333 : putout (int c, void *out)
334 : {
335 : return (putc (c, (FILE *) out));
336 : }
337 :
338 : /* getin from file descriptor
339 : ** --------------------------
340 : */
341 : int
342 : getin (void *in)
343 : {
344 : return (getc ((FILE *) in));
345 : }
346 :
347 :
348 : /* Main function
349 : ** -------------
350 : **
351 : */
352 : int
353 : main (int argc, char *argv[])
354 : {
355 : FILE *wbmp_file;
356 : Wbmp *wbmp;
357 :
358 : wbmp_file = fopen (argv[1], "rb");
359 : if (wbmp_file)
360 : {
361 : readwbmp (&getin, wbmp_file, &wbmp);
362 :
363 : #ifdef __VIEW
364 :
365 : #ifdef __DEBUG
366 : printf ("\nVIEWING IMAGE\n");
367 : #endif
368 :
369 : printwbmp (wbmp);
370 : #endif
371 :
372 : #ifdef __WRITE
373 :
374 : #ifdef __DEBUG
375 : printf ("\nDUMPING WBMP to STDOUT\n");
376 : #endif
377 :
378 : writewbmp (wbmp, &putout, stdout);
379 : #endif
380 :
381 : freewbmp (wbmp);
382 : fclose (wbmp_file);
383 : }
384 : }
385 : #endif
|