1 /* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap *
2  *
3  * Copyright (C) 1989 by Paul Haeberli <paul@manray.sgi.com>. *
4  *
5  * pnmtoxwd.c - read a portable anymap and produce a color X11 window dump
6  *
7  * Copyright (C) 1989, 1991 by Jef Poskanzer.
8  *
9  * gcc -g -o g3toxwd -O2 g3toxwd.c
10  *
11  * Permission to use, copy, modify, and distribute this software and its *
12  * documentation for any purpose and without fee is hereby granted, provided *
13  * that the above copyright notice appear in all copies and that both that *
14  * copyright notice and this permission notice appear in supporting *
15  * documentation.  This software is provided "as is" without express or *
16  * implied warranty. *
17  *
18  * Update aug 31,1993, Chel van Gennip, combined two programs, delated large
19  * array and added simple scaling to improve speed.
20  *
21  * Update 22 may 1994, better EOF handling by transmission errors chel. Added
22  * -skiprows for long faxes.
23  *
24  * $Log: g3toxwd.c,v $
25  * Revision 1.2  2003/10/03 11:36:03  gert
26  * fix some return types and prototypes (Debian/ABA)
27  *
28  * Revision 1.1  2003/10/03 11:34:56  gert
29  * G3 -> X11 xwd, initial checkin
30  *
31  *
32  */
33 
34 #include <sys/types.h>
35 #include <ctype.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 typedef unsigned char bit;
41 
42 #define PBM_WHITE 0
43 #define PBM_BLACK 1
44 #define pm_error(a,b,c,d,e,f) {fprintf(stderr,a,b,c,d,e,f);fprintf(stderr,"\n");}
45 #define pm_message(a,b,c,d,e,f) {fprintf(stderr,a,b,c,d,e,f);fprintf(stderr,"\n");}
46 #define pm_usage(a) { fprintf(stderr,"usage: %s\n",a); exit(7); }
47 #define pbm_allocrow(a) (bit*)malloc(a)
48 
49 /* x11wd.h - the following defs are taken from various X.V11R2 header files */
50 
51 #ifndef _X11WD_H_
52 #define _X11WD_H_
53 
54 #define LSBFirst	0
55 #define MSBFirst	1
56 
57 #define XYBitmap	0
58 #define XYPixmap	1
59 #define ZPixmap		2
60 
61 #define StaticGray	0
62 #define GrayScale	1
63 #define StaticColor	2
64 #define PseudoColor	3
65 #define TrueColor	4
66 #define DirectColor	5
67 
68 typedef unsigned long xwdval;
69 
70 #define X11WD_FILE_VERSION 7
71 typedef struct {
72     xwdval header_size;		/* Size of the entire file header (bytes). */
73     xwdval file_version;	/* X11WD_FILE_VERSION */
74     xwdval pixmap_format;	/* Pixmap format */
75     xwdval pixmap_depth;	/* Pixmap depth */
76     xwdval pixmap_width;	/* Pixmap width */
77     xwdval pixmap_height;	/* Pixmap height */
78     xwdval xoffset;		/* Bitmap x offset */
79     xwdval byte_order;		/* MSBFirst, LSBFirst */
80     xwdval bitmap_unit;		/* Bitmap unit */
81     xwdval bitmap_bit_order;	/* MSBFirst, LSBFirst */
82     xwdval bitmap_pad;		/* Bitmap scanline pad */
83     xwdval bits_per_pixel;	/* Bits per pixel */
84     xwdval bytes_per_line;	/* Bytes per scanline */
85     xwdval visual_class;	/* Class of colormap */
86     xwdval red_mask;		/* Z red mask */
87     xwdval green_mask;		/* Z green mask */
88     xwdval blue_mask;		/* Z blue mask */
89     xwdval bits_per_rgb;	/* Log base 2 of distinct color values */
90     xwdval colormap_entries;	/* Number of entries in colormap */
91     xwdval ncolors;		/* Number of Color structures */
92     xwdval window_width;	/* Window width */
93     xwdval window_height;	/* Window height */
94     long window_x;		/* Window upper left X coordinate */
95     long window_y;		/* Window upper left Y coordinate */
96     xwdval window_bdrwidth;	/* Window border width */
97 } X11WDFileHeader;
98 
99 typedef struct {
100     unsigned long pixel;
101     unsigned short red, green, blue;
102     char flags;			/* do_red, do_green, do_blue */
103     char pad;
104 } X11XColor;
105 
106 #endif	/* _X11WD_H_ */
107 
108 /* g3.h - header file for group 3 FAX compression filters from pm package */
109 
110 #ifndef _G3_H_
111 #define _G3_H_
112 
113 typedef struct tableentry {
114     int tabid;
115     int code;
116     int length;
117     int count;
118 } tableentry;
119 
120 #define TWTABLE		23
121 #define MWTABLE		24
122 #define TBTABLE		25
123 #define MBTABLE		26
124 #define EXTABLE		27
125 #define VRTABLE		28
126 
127 static struct tableentry twtable[]=
128 {
129     {TWTABLE, 0x35, 8, 0},
130     {TWTABLE, 0x7, 6, 1},
131     {TWTABLE, 0x7, 4, 2},
132     {TWTABLE, 0x8, 4, 3},
133     {TWTABLE, 0xb, 4, 4},
134     {TWTABLE, 0xc, 4, 5},
135     {TWTABLE, 0xe, 4, 6},
136     {TWTABLE, 0xf, 4, 7},
137     {TWTABLE, 0x13, 5, 8},
138     {TWTABLE, 0x14, 5, 9},
139     {TWTABLE, 0x7, 5, 10},
140     {TWTABLE, 0x8, 5, 11},
141     {TWTABLE, 0x8, 6, 12},
142     {TWTABLE, 0x3, 6, 13},
143     {TWTABLE, 0x34, 6, 14},
144     {TWTABLE, 0x35, 6, 15},
145     {TWTABLE, 0x2a, 6, 16},
146     {TWTABLE, 0x2b, 6, 17},
147     {TWTABLE, 0x27, 7, 18},
148     {TWTABLE, 0xc, 7, 19},
149     {TWTABLE, 0x8, 7, 20},
150     {TWTABLE, 0x17, 7, 21},
151     {TWTABLE, 0x3, 7, 22},
152     {TWTABLE, 0x4, 7, 23},
153     {TWTABLE, 0x28, 7, 24},
154     {TWTABLE, 0x2b, 7, 25},
155     {TWTABLE, 0x13, 7, 26},
156     {TWTABLE, 0x24, 7, 27},
157     {TWTABLE, 0x18, 7, 28},
158     {TWTABLE, 0x2, 8, 29},
159     {TWTABLE, 0x3, 8, 30},
160     {TWTABLE, 0x1a, 8, 31},
161     {TWTABLE, 0x1b, 8, 32},
162     {TWTABLE, 0x12, 8, 33},
163     {TWTABLE, 0x13, 8, 34},
164     {TWTABLE, 0x14, 8, 35},
165     {TWTABLE, 0x15, 8, 36},
166     {TWTABLE, 0x16, 8, 37},
167     {TWTABLE, 0x17, 8, 38},
168     {TWTABLE, 0x28, 8, 39},
169     {TWTABLE, 0x29, 8, 40},
170     {TWTABLE, 0x2a, 8, 41},
171     {TWTABLE, 0x2b, 8, 42},
172     {TWTABLE, 0x2c, 8, 43},
173     {TWTABLE, 0x2d, 8, 44},
174     {TWTABLE, 0x4, 8, 45},
175     {TWTABLE, 0x5, 8, 46},
176     {TWTABLE, 0xa, 8, 47},
177     {TWTABLE, 0xb, 8, 48},
178     {TWTABLE, 0x52, 8, 49},
179     {TWTABLE, 0x53, 8, 50},
180     {TWTABLE, 0x54, 8, 51},
181     {TWTABLE, 0x55, 8, 52},
182     {TWTABLE, 0x24, 8, 53},
183     {TWTABLE, 0x25, 8, 54},
184     {TWTABLE, 0x58, 8, 55},
185     {TWTABLE, 0x59, 8, 56},
186     {TWTABLE, 0x5a, 8, 57},
187     {TWTABLE, 0x5b, 8, 58},
188     {TWTABLE, 0x4a, 8, 59},
189     {TWTABLE, 0x4b, 8, 60},
190     {TWTABLE, 0x32, 8, 61},
191     {TWTABLE, 0x33, 8, 62},
192     {TWTABLE, 0x34, 8, 63},
193 };
194 
195 static struct tableentry mwtable[]=
196 {
197     {MWTABLE, 0x1b, 5, 64},
198     {MWTABLE, 0x12, 5, 128},
199     {MWTABLE, 0x17, 6, 192},
200     {MWTABLE, 0x37, 7, 256},
201     {MWTABLE, 0x36, 8, 320},
202     {MWTABLE, 0x37, 8, 384},
203     {MWTABLE, 0x64, 8, 448},
204     {MWTABLE, 0x65, 8, 512},
205     {MWTABLE, 0x68, 8, 576},
206     {MWTABLE, 0x67, 8, 640},
207     {MWTABLE, 0xcc, 9, 704},
208     {MWTABLE, 0xcd, 9, 768},
209     {MWTABLE, 0xd2, 9, 832},
210     {MWTABLE, 0xd3, 9, 896},
211     {MWTABLE, 0xd4, 9, 960},
212     {MWTABLE, 0xd5, 9, 1024},
213     {MWTABLE, 0xd6, 9, 1088},
214     {MWTABLE, 0xd7, 9, 1152},
215     {MWTABLE, 0xd8, 9, 1216},
216     {MWTABLE, 0xd9, 9, 1280},
217     {MWTABLE, 0xda, 9, 1344},
218     {MWTABLE, 0xdb, 9, 1408},
219     {MWTABLE, 0x98, 9, 1472},
220     {MWTABLE, 0x99, 9, 1536},
221     {MWTABLE, 0x9a, 9, 1600},
222     {MWTABLE, 0x18, 6, 1664},
223     {MWTABLE, 0x9b, 9, 1728},
224 };
225 
226 static struct tableentry tbtable[]=
227 {
228     {TBTABLE, 0x37, 10, 0},
229     {TBTABLE, 0x2, 3, 1},
230     {TBTABLE, 0x3, 2, 2},
231     {TBTABLE, 0x2, 2, 3},
232     {TBTABLE, 0x3, 3, 4},
233     {TBTABLE, 0x3, 4, 5},
234     {TBTABLE, 0x2, 4, 6},
235     {TBTABLE, 0x3, 5, 7},
236     {TBTABLE, 0x5, 6, 8},
237     {TBTABLE, 0x4, 6, 9},
238     {TBTABLE, 0x4, 7, 10},
239     {TBTABLE, 0x5, 7, 11},
240     {TBTABLE, 0x7, 7, 12},
241     {TBTABLE, 0x4, 8, 13},
242     {TBTABLE, 0x7, 8, 14},
243     {TBTABLE, 0x18, 9, 15},
244     {TBTABLE, 0x17, 10, 16},
245     {TBTABLE, 0x18, 10, 17},
246     {TBTABLE, 0x8, 10, 18},
247     {TBTABLE, 0x67, 11, 19},
248     {TBTABLE, 0x68, 11, 20},
249     {TBTABLE, 0x6c, 11, 21},
250     {TBTABLE, 0x37, 11, 22},
251     {TBTABLE, 0x28, 11, 23},
252     {TBTABLE, 0x17, 11, 24},
253     {TBTABLE, 0x18, 11, 25},
254     {TBTABLE, 0xca, 12, 26},
255     {TBTABLE, 0xcb, 12, 27},
256     {TBTABLE, 0xcc, 12, 28},
257     {TBTABLE, 0xcd, 12, 29},
258     {TBTABLE, 0x68, 12, 30},
259     {TBTABLE, 0x69, 12, 31},
260     {TBTABLE, 0x6a, 12, 32},
261     {TBTABLE, 0x6b, 12, 33},
262     {TBTABLE, 0xd2, 12, 34},
263     {TBTABLE, 0xd3, 12, 35},
264     {TBTABLE, 0xd4, 12, 36},
265     {TBTABLE, 0xd5, 12, 37},
266     {TBTABLE, 0xd6, 12, 38},
267     {TBTABLE, 0xd7, 12, 39},
268     {TBTABLE, 0x6c, 12, 40},
269     {TBTABLE, 0x6d, 12, 41},
270     {TBTABLE, 0xda, 12, 42},
271     {TBTABLE, 0xdb, 12, 43},
272     {TBTABLE, 0x54, 12, 44},
273     {TBTABLE, 0x55, 12, 45},
274     {TBTABLE, 0x56, 12, 46},
275     {TBTABLE, 0x57, 12, 47},
276     {TBTABLE, 0x64, 12, 48},
277     {TBTABLE, 0x65, 12, 49},
278     {TBTABLE, 0x52, 12, 50},
279     {TBTABLE, 0x53, 12, 51},
280     {TBTABLE, 0x24, 12, 52},
281     {TBTABLE, 0x37, 12, 53},
282     {TBTABLE, 0x38, 12, 54},
283     {TBTABLE, 0x27, 12, 55},
284     {TBTABLE, 0x28, 12, 56},
285     {TBTABLE, 0x58, 12, 57},
286     {TBTABLE, 0x59, 12, 58},
287     {TBTABLE, 0x2b, 12, 59},
288     {TBTABLE, 0x2c, 12, 60},
289     {TBTABLE, 0x5a, 12, 61},
290     {TBTABLE, 0x66, 12, 62},
291     {TBTABLE, 0x67, 12, 63},
292 };
293 
294 static struct tableentry mbtable[]=
295 {
296     {MBTABLE, 0xf, 10, 64},
297     {MBTABLE, 0xc8, 12, 128},
298     {MBTABLE, 0xc9, 12, 192},
299     {MBTABLE, 0x5b, 12, 256},
300     {MBTABLE, 0x33, 12, 320},
301     {MBTABLE, 0x34, 12, 384},
302     {MBTABLE, 0x35, 12, 448},
303     {MBTABLE, 0x6c, 13, 512},
304     {MBTABLE, 0x6d, 13, 576},
305     {MBTABLE, 0x4a, 13, 640},
306     {MBTABLE, 0x4b, 13, 704},
307     {MBTABLE, 0x4c, 13, 768},
308     {MBTABLE, 0x4d, 13, 832},
309     {MBTABLE, 0x72, 13, 896},
310     {MBTABLE, 0x73, 13, 960},
311     {MBTABLE, 0x74, 13, 1024},
312     {MBTABLE, 0x75, 13, 1088},
313     {MBTABLE, 0x76, 13, 1152},
314     {MBTABLE, 0x77, 13, 1216},
315     {MBTABLE, 0x52, 13, 1280},
316     {MBTABLE, 0x53, 13, 1344},
317     {MBTABLE, 0x54, 13, 1408},
318     {MBTABLE, 0x55, 13, 1472},
319     {MBTABLE, 0x5a, 13, 1536},
320     {MBTABLE, 0x5b, 13, 1600},
321     {MBTABLE, 0x64, 13, 1664},
322     {MBTABLE, 0x65, 13, 1728},
323 };
324 
325 static struct tableentry extable[]=
326 {
327     {EXTABLE, 0x8, 11, 1792},
328     {EXTABLE, 0xc, 11, 1856},
329     {EXTABLE, 0xd, 11, 1920},
330     {EXTABLE, 0x12, 12, 1984},
331     {EXTABLE, 0x13, 12, 2048},
332     {EXTABLE, 0x14, 12, 2112},
333     {EXTABLE, 0x15, 12, 2176},
334     {EXTABLE, 0x16, 12, 2240},
335     {EXTABLE, 0x17, 12, 2304},
336     {EXTABLE, 0x1c, 12, 2368},
337     {EXTABLE, 0x1d, 12, 2432},
338     {EXTABLE, 0x1e, 12, 2496},
339     {EXTABLE, 0x1f, 12, 2560},
340 };
341 
342 #endif	/* _G3_H_ */
343 
344 void skiptoeol (void);
345 
346 FILE *
pm_openr(name)347   pm_openr (name)
348      char *name;
349 {
350     FILE *f;
351 
352     if (strcmp (name, "-") == 0)
353 	f = stdin;
354     else {
355 	f = fopen (name, "r");
356 	if (f == NULL) {
357 	    perror (name);
358 	    exit (1);
359 	}
360     }
361     return f;
362 }
363 
pm_keymatch(str,keyword,minchars)364 int pm_keymatch (str, keyword, minchars)
365      char *str;
366      char *keyword;
367      int minchars;
368 {
369     register int len;
370 
371     len = strlen (str);
372     if (len < minchars)
373 	return 0;
374     while (--len >= 0) {
375 	register char c1, c2;
376 
377 	c1 = *str++;
378 	c2 = *keyword++;
379 	if (c2 == '\0')
380 	    return 0;
381 	if (isupper (c1))
382 	    c1 = tolower (c1);
383 	if (isupper (c2))
384 	    c1 = tolower (c2);
385 	if (c1 != c2)
386 	    return 0;
387     }
388     return 1;
389 }
390 
pm_writebigshort(out,s)391 int pm_writebigshort (out, s)
392      FILE *out;
393      short s;
394 {
395     if (putc ((s >> 8) & 0xff, out) == EOF)
396 	return -1;
397     if (putc (s & 0xff, out) == EOF)
398 	return -1;
399     return 0;
400 }
401 
pm_writebiglong(out,l)402 int pm_writebiglong (out, l)
403      FILE *out;
404      long l;
405 {
406     if (putc ((l >> 24) & 0xff, out) == EOF)
407 	return -1;
408     if (putc ((l >> 16) & 0xff, out) == EOF)
409 	return -1;
410     if (putc ((l >> 8) & 0xff, out) == EOF)
411 	return -1;
412     if (putc (l & 0xff, out) == EOF)
413 	return -1;
414     return 0;
415 }
416 
417 static int doubleheight = 1;
418 static hscale = 100;
419 static vscale = 100;
420 
421 static void putinit (), putbit (), putrest (), putitem ();
422 static int item, bitsperitem;
423 static char *line;
424 static int bytecnt;
425 
426 #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
427 #define MAXCOLS 1728
428 #define MAXROWS 4300		/* up to two pages long */
429 #define XWDCOLS 1000
430 #define XWDROWS XWDCOLS*290/215
431 
432 int eof = 0;
433 int eols;
434 int rawzeros;
435 int shdata;
436 int kludge;
437 int reversebits;
438 int stretch;
439 
440 #define WHASHA 3510
441 #define WHASHB 1178
442 
443 #define BHASHA 293
444 #define BHASHB 2695
445 
446 #define HASHSIZE 1021
447 tableentry *whash[HASHSIZE];
448 tableentry *bhash[HASHSIZE];
449 
450 static FILE *ifp;
451 static int shbit = 0;
452 static int eof_err = 0;
rawgetbit()453 static inline int rawgetbit ()
454 {
455     int b;
456 
457     if (eof_err) {
458 	rawzeros = 20;
459 	return (1);
460     }
461     if ((shbit & 0xff) == 0) {
462 	shdata = getc (ifp);
463 	if (shdata == EOF) {
464 	    eof_err++;
465 	    pm_error ("EOF / read error at line %d", eols, 0, 0, 0, 0);
466 	}
467 	shbit = reversebits ? 0x01 : 0x80;
468     }
469     if (shdata & shbit) {
470 	rawzeros = 0;
471 	b = 1;
472     } else {
473 	rawzeros++;
474 	b = 0;
475     }
476     if (reversebits)
477 	shbit <<= 1;
478     else
479 	shbit >>= 1;
480     return b;
481 }
482 
addtohash(hash,te,n,a,b)483 addtohash (hash, te, n, a, b)
484      tableentry *hash[];
485      tableentry *te;
486      int n, a, b;
487 {
488     unsigned int pos;
489 
490     while (n--) {
491 	pos = ((te->length + a) * (te->code + b)) % HASHSIZE;
492 	if (hash[pos] != 0)
493 	    pm_error (
494 			 "internal error: addtohash fatal hash collision",
495 			 0, 0, 0, 0, 0);
496 	hash[pos] = te;
497 	te++;
498     }
499 }
500 
501 static inline tableentry *
hashfind(hash,length,code,a,b)502   hashfind (hash, length, code, a, b)
503      tableentry *hash[];
504      int length, code;
505      int a, b;
506 {
507     unsigned int pos;
508     tableentry *te;
509 
510     pos = ((length + a) * (code + b)) % HASHSIZE;
511     if (pos < 0 || pos >= HASHSIZE)
512 	pm_error (
513 	      "internal error: bad hash position, length %d code %d pos %d",
514 		     length, code, pos, 0, 0);
515     te = hash[pos];
516     return ((te && te->length == length && te->code == code) ? te : 0);
517 }
518 
getfaxrow(row,bitrow)519 getfaxrow (row, bitrow)
520      int row;
521      bit *bitrow;
522 {
523     int col;
524     bit *bP;
525     int curlen, curcode, nextbit;
526     int count, color;
527     tableentry *te;
528 
529     for (col = 0, bP = bitrow; col < MAXCOLS; ++col, ++bP)
530 	*bP = PBM_WHITE;
531     col = 0;
532     rawzeros = 0;
533     curlen = 0;
534     curcode = 0;
535     color = 1;
536     count = 0;
537     while (!eof) {
538 	if (col >= MAXCOLS) {
539 	    skiptoeol ();
540 	    return (col);
541 	}
542 	do {
543 	    if (rawzeros >= 11) {
544 		nextbit = rawgetbit ();
545 		if (nextbit) {
546 		    if (col == 0)
547 			/* XXX should be 6 */
548 			eof = (++eols == 3);
549 		    else
550 			eols = 0;
551 #ifdef notdef
552 		    if (col && col < 1728)
553 			pm_message (
554 				       "warning, row %d short (len %d)",
555 				       row, col, 0, 0, 0);
556 #endif	/* notdef */
557 		    return (col);
558 		}
559 	    } else
560 		nextbit = rawgetbit ();
561 	    curcode = (curcode << 1) + nextbit;
562 	    curlen++;
563 	} while (curcode <= 0);
564 	if (curlen > 13) {
565 	    pm_message (
566 			   "bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL",
567 			   row, col, curlen, curcode, 0);
568 	    skiptoeol ();
569 	    return (col);
570 	}
571 	if (color) {
572 	    if (curlen < 4)
573 		continue;
574 	    te = hashfind (whash, curlen, curcode, WHASHA, WHASHB);
575 	} else {
576 	    if (curlen < 2)
577 		continue;
578 	    te = hashfind (bhash, curlen, curcode, BHASHA, BHASHB);
579 	}
580 	if (!te)
581 	    continue;
582 	switch (te->tabid) {
583 	case TWTABLE:
584 	case TBTABLE:
585 	    count += te->count;
586 	    if (col + count > MAXCOLS)
587 		count = MAXCOLS - col;
588 	    if (count > 0) {
589 		if (color) {
590 		    col += count;
591 		    count = 0;
592 		} else {
593 		    for (; count > 0; --count, ++col)
594 			bitrow[col] = PBM_BLACK;
595 		}
596 	    }
597 	    curcode = 0;
598 	    curlen = 0;
599 	    color = !color;
600 	    break;
601 	case MWTABLE:
602 	case MBTABLE:
603 	    count += te->count;
604 	    curcode = 0;
605 	    curlen = 0;
606 	    break;
607 	case EXTABLE:
608 	    count += te->count;
609 	    curcode = 0;
610 	    curlen = 0;
611 	    break;
612 	default:
613 	    pm_error ("internal bad poop", 0, 0, 0, 0, 0);
614 	}
615     }
616     return (0);
617 }
618 
skiptoeol()619 void skiptoeol ()
620 {
621     while (rawzeros < 11)
622 	(void) rawgetbit ();
623     for (;;) {
624 	if (rawgetbit ())
625 	    break;
626     }
627 }
628 
629 static X11WDFileHeader h11;
630 static char *dumpname;
631 
putinit()632 static void putinit ()
633 {
634     int i;
635     X11XColor color;
636 
637     /* Init outfil. */
638     /* Set up the header. */
639     h11.header_size = sizeof (h11) + strlen (dumpname) + 1;
640     h11.file_version = X11WD_FILE_VERSION;
641     h11.pixmap_format = ZPixmap;
642     h11.pixmap_width = XWDCOLS;
643     h11.pixmap_height = XWDROWS;
644     h11.xoffset = 0;
645     h11.byte_order = MSBFirst;
646     h11.bitmap_bit_order = MSBFirst;
647     h11.window_width = XWDCOLS;
648     h11.window_height = XWDROWS;
649     h11.window_x = 0;
650     h11.window_y = 0;
651     h11.window_bdrwidth = 0;
652 
653     h11.pixmap_depth = 1;
654     h11.bits_per_pixel = 1;
655     h11.colormap_entries = 2;
656     h11.ncolors = 2;
657     h11.bytes_per_line = (XWDCOLS + 7) / 8;
658     h11.bitmap_unit = 8;
659     h11.bitmap_pad = 8;
660     h11.visual_class = StaticGray;
661     h11.red_mask = 0;
662     h11.green_mask = 0;
663     h11.blue_mask = 0;
664     h11.bits_per_rgb = h11.pixmap_depth;
665 
666     /* Write out the header in big-endian order. */
667     pm_writebiglong (stdout, h11.header_size);
668     pm_writebiglong (stdout, h11.file_version);
669     pm_writebiglong (stdout, h11.pixmap_format);
670     pm_writebiglong (stdout, h11.pixmap_depth);
671     pm_writebiglong (stdout, h11.pixmap_width);
672     pm_writebiglong (stdout, h11.pixmap_height);
673     pm_writebiglong (stdout, h11.xoffset);
674     pm_writebiglong (stdout, h11.byte_order);
675     pm_writebiglong (stdout, h11.bitmap_unit);
676     pm_writebiglong (stdout, h11.bitmap_bit_order);
677     pm_writebiglong (stdout, h11.bitmap_pad);
678     pm_writebiglong (stdout, h11.bits_per_pixel);
679     pm_writebiglong (stdout, h11.bytes_per_line);
680     pm_writebiglong (stdout, h11.visual_class);
681     pm_writebiglong (stdout, h11.red_mask);
682     pm_writebiglong (stdout, h11.green_mask);
683     pm_writebiglong (stdout, h11.blue_mask);
684     pm_writebiglong (stdout, h11.bits_per_rgb);
685     pm_writebiglong (stdout, h11.colormap_entries);
686     pm_writebiglong (stdout, h11.ncolors);
687     pm_writebiglong (stdout, h11.window_width);
688     pm_writebiglong (stdout, h11.window_height);
689     pm_writebiglong (stdout, h11.window_x);
690     pm_writebiglong (stdout, h11.window_y);
691     pm_writebiglong (stdout, h11.window_bdrwidth);
692 
693     /* Write out the dump name. */
694     fwrite (dumpname, 1, strlen (dumpname) + 1, stdout);
695 
696     /* Write out the colormap, big-endian order. */
697     color.flags = 7;
698     color.pad = 0;
699     for (i = 0; i < 2; ++i) {
700 	color.pixel = i;
701 
702 	/* Stupid hack because xloadimage and xwud disagree on * how to
703 	 * interpret bitmaps. */
704 	if (1)
705 	    color.red = (long) (2 - 1 - i) * 65535 / (2 - 1);
706 	else
707 	    color.red = (long) i *65535 / (2 - 1);
708 
709 	color.green = color.red;
710 	color.blue = color.red;
711 	pm_writebiglong (stdout, color.pixel);
712 	pm_writebigshort (stdout, color.red);
713 	pm_writebigshort (stdout, color.green);
714 	pm_writebigshort (stdout, color.blue);
715 	putc (color.flags, stdout);
716 	putc (color.pad, stdout);
717     }
718 }
719 
putrest()720 static void putrest ()
721 {
722 }
723 
xwd_writerow(FILE * fd,bit * writerow,int wcols)724 static void xwd_writerow (FILE * fd, bit * writerow, int wcols)
725 {
726     register int bitshift;
727     unsigned char byte;
728     register int s, col;
729 
730     bitshift = 7;
731     byte = 0;
732     for (col = 0; col < XWDCOLS; col++) {
733 	s = writerow[col] & 1;
734 
735 	byte |= s << bitshift;
736 	bitshift -= h11.bits_per_pixel;
737 	if (bitshift < 0) {
738 	    putchar (byte);
739 	    bitshift = 7;
740 	    byte = 0;
741 	}
742     }
743     if (bitshift < 7)
744 	putchar (byte);
745 };
746 
main(argc,argv)747 int main (argc, argv)
748      int argc;
749      char *argv[];
750 {
751     int argn, rows, wrows, cols, wcols, row, wrow, col, wcol, i;
752     int vval, hval, skiprows;
753     bit *readrow, *writerow, *bP, *wbP, bitval;
754     float aspect, scale;
755     int format;
756     register int nzcol;
757 
758     char *usage =
759     "g3toxwd [-kludge] [-reversebits] [-scale N] [-aspect N] [-skiprows N] [g3file]";
760 
761     argn = 1;
762     kludge = 0;
763     reversebits = 0;
764     aspect = 1.0;
765     scale = (1.0 * XWDCOLS) / (1.0 * MAXCOLS);
766     skiprows = 0;
767     dumpname = "";
768 
769     /* Check for flags. */
770     while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
771 	if (pm_keymatch (argv[argn], "-kludge", 2))
772 	    kludge = 1;
773 	else if (pm_keymatch (argv[argn], "-reversebits", 2))
774 	    reversebits = 1;
775 	else if (pm_keymatch (argv[argn], "-aspect", 2)) {
776 	    ++argn;
777 	    if (argn == argc || sscanf (argv[argn], "%f", &aspect) != 1)
778 		pm_usage (usage);
779 	} else if (pm_keymatch (argv[argn], "-scale", 2)) {
780 	    ++argn;
781 	    if (argn == argc || sscanf (argv[argn], "%f", &scale) != 1)
782 		pm_usage (usage);
783 	} else if (pm_keymatch (argv[argn], "-skiprows", 2)) {
784 	    ++argn;
785 	    if (argn == argc || sscanf (argv[argn], "%d", &skiprows) != 1)
786 		pm_usage (usage);
787 	} else if (pm_keymatch (argv[argn], "-name", 2)) {
788 	    ++argn;
789 	    dumpname = argv[argn];
790 	    if (argn == argc)
791 		pm_usage (usage);
792 	} else
793 	    pm_usage (usage);
794 	argn++;
795     }
796 
797     if (argn < argc) {
798 	if (dumpname[0] == '\0')
799 	    dumpname = argv[argn];
800 	ifp = pm_openr (argv[argn]);
801 	argn++;
802     } else {
803 	if (dumpname[0] == '\0')
804 	    dumpname = "stdin";
805 	ifp = stdin;
806     }
807 
808     if (argn != argc)
809 	pm_usage (usage);
810 
811     vscale = aspect * scale * 100;
812     hscale = scale * 100;
813     eols = 0;
814 
815     putinit ();
816 
817     if (kludge) {
818 	/* Skip extra lines to get in sync. */
819 	skiptoeol ();
820 	skiptoeol ();
821 	skiptoeol ();
822     }
823     skiptoeol ();
824     for (i = 0; i < HASHSIZE; ++i)
825 	whash[i] = bhash[i] = (tableentry *) 0;
826     addtohash (whash, twtable, TABSIZE (twtable), WHASHA, WHASHB);
827     addtohash (whash, mwtable, TABSIZE (mwtable), WHASHA, WHASHB);
828     addtohash (whash, extable, TABSIZE (extable), WHASHA, WHASHB);
829     addtohash (bhash, tbtable, TABSIZE (tbtable), BHASHA, BHASHB);
830     addtohash (bhash, mbtable, TABSIZE (mbtable), BHASHA, BHASHB);
831     addtohash (bhash, extable, TABSIZE (extable), BHASHA, BHASHB);
832 
833     wcols = (MAXCOLS * hscale) / 100;
834     writerow = pbm_allocrow (wcols);
835     readrow = pbm_allocrow (MAXCOLS);
836     vval = wrow = row = 0;
837     while (skiprows > 0) {
838 	hval = wcol = 0;
839 	bP = readrow;
840 	wbP = writerow;
841 	col = getfaxrow (row, readrow);
842 	skiprows--;
843     }
844     while (row < MAXROWS) {
845 	for (col = 0, bP = writerow; col < (MAXCOLS * hscale) / 100;
846 	     ++col, ++bP)
847 	    *bP = PBM_WHITE;
848 	cols = 1;
849 	while (vval < 100) {
850 	    if (row < MAXROWS) {
851 		hval = wcol = 0;
852 		bP = readrow;
853 		wbP = writerow;
854 		col = getfaxrow (row, readrow);
855 		col--;
856 		while ((col > 0) && (readrow[col] == PBM_WHITE))
857 		    col--;
858 		col++;
859 		if (col > cols)
860 		    cols = col;
861 		wcols = (cols * hscale) / 100;
862 		col = 0;
863 		while (col < cols) {
864 		    bitval = *wbP;
865 		    while (hval < 100) {
866 			if (col++ < cols)
867 			    if (*bP++ == PBM_BLACK)
868 				bitval = PBM_BLACK;
869 			hval += hscale;
870 		    }
871 		    while (hval >= 100) {
872 			if (wcol++ < wcols)
873 			    *wbP++ = bitval;
874 			hval -= 100;
875 		    }
876 		}		/* while(col */
877 	    }			/* if(row */
878 	    vval += vscale;
879 	    row++;
880 	}			/* while vval */
881 	while (vval >= 100) {
882 	    if (wrow < XWDROWS) {
883 		xwd_writerow (stdout, writerow, wcols);
884 		wrow++;
885 	    }
886 	    vval -= 100;
887 	}
888 	if (eof)
889 	    break;
890     }
891     for (col = 0, bP = writerow; col < (MAXCOLS * hscale) / 100;
892 	 ++col, ++bP)
893 	*bP = PBM_WHITE;
894     while (wrow < XWDROWS) {
895 	xwd_writerow (stdout, writerow, wcols);
896 	wrow++;
897     }
898 
899     return 0;
900 }
901