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