xref: /PHP-7.4/ext/gd/libgd/wbmp.c (revision 1cb2079d)
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