1 /* Copyright (C) 1992, 1994, 1998, 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: scfdgen.c,v 1.2.6.1.2.1 2003/01/17 00:49:05 giles Exp $ */
20 /* Generate the CCITTFaxDecode tables */
21 #include "stdio_.h"		/* includes std.h */
22 #include "scf.h"
23 #include "malloc_.h"
24 #include "memory_.h"
25 
26 typedef void (*cfd_node_proc) (P6(cfd_node *, cfd_node *,
27 				  uint, int, int, int));
28 typedef void (*cfd_enum_proc) (P4(cfd_node_proc,
29 				  cfd_node *, cfd_node *, int));
30 private void cfd_build_tree(P4(cfd_node *, cfd_enum_proc, int, FILE *));
31 private void cfd_enumerate_white(P4(cfd_node_proc,
32 				    cfd_node *, cfd_node *, int));
33 private void cfd_enumerate_black(P4(cfd_node_proc,
34 				    cfd_node *, cfd_node *, int));
35 private void cfd_enumerate_2d(P4(cfd_node_proc,
36 				 cfd_node *, cfd_node *, int));
37 private void cfd_enumerate_uncompressed(P4(cfd_node_proc,
38 					   cfd_node *, cfd_node *, int));
39 
main()40 main()
41 {
42     FILE *out = fopen("scfdtab.c", "w");
43     cfd_node area[1 << max(cfd_white_initial_bits, cfd_black_initial_bits)];
44 
45     fputs("/* Copyright (C) 1992, 1993, 1998, 1999 Aladdin Enterprises.  All rights reserved. */\n\n", out);
46     fputs("/* $Id: scfdgen.c,v 1.2.6.1.2.1 2003/01/17 00:49:05 giles Exp $ */\n", out);
47     fputs("/* Tables for CCITTFaxDecode filter. */\n\n", out);
48     fputs("/* This file was generated automatically.  It is governed by the same terms */\n", out);
49     fputs("/* as the files scfetab.c and scfdgen.c from which it was derived. */\n", out);
50     fputs("/* Consult those files for the licensing terms and conditions. */\n\n", out);
51     fputs("#include \"std.h\"\n", out);
52     fputs("#include \"scommon.h\"\t\t/* for scf.h */\n", out);
53     fputs("#include \"scf.h\"\n\n", out);
54     fputs("/* White decoding table. */\n", out);
55     fputs("const cfd_node cf_white_decode[] = {\n", out);
56     cfd_build_tree(area, cfd_enumerate_white, cfd_white_initial_bits, out);
57     fputs("\n};\n\n", out);
58     fputs("/* Black decoding table. */\n", out);
59     fputs("const cfd_node cf_black_decode[] = {\n", out);
60     cfd_build_tree(area, cfd_enumerate_black, cfd_black_initial_bits, out);
61     fputs("\n};\n\n", out);
62     fputs("/* 2-D decoding table. */\n", out);
63     fputs("const cfd_node cf_2d_decode[] = {\n", out);
64     cfd_build_tree(area, cfd_enumerate_2d, cfd_2d_initial_bits, out);
65     fputs("\n};\n\n", out);
66     fputs("/* Uncompresssed decoding table. */\n", out);
67     fputs("const cfd_node cf_uncompressed_decode[] = {\n", out);
68     cfd_build_tree(area, cfd_enumerate_uncompressed, cfd_uncompressed_initial_bits, out);
69     fputs("\n};\n\n", out);
70     fputs("/* Dummy executable code to pacify compilers. */\n", out);
71     fputs("void scfdtab_dummy(P0());\n", out);
72     fputs("void\nscfdtab_dummy()\n{\n}\n", out);
73     fclose(out);
74     return 0;
75 }
76 
77 /* Initialize first-level leaves, count second-level nodes. */
78 private void
cfd_count_nodes(cfd_node * tree,cfd_node * ignore_extn,uint code,int code_length,int run_length,int initial_bits)79 cfd_count_nodes(cfd_node * tree, cfd_node * ignore_extn,
80 		uint code, int code_length, int run_length, int initial_bits)
81 {
82     if (code_length <= initial_bits) {
83 	/* Initialize one or more first-level leaves. */
84 	int sh = initial_bits - code_length;
85 	cfd_node *np = &tree[code << sh];
86 	int i;
87 
88 	for (i = 1 << sh; i > 0; i--, np++)
89 	    np->run_length = run_length,
90 		np->code_length = code_length;
91     } else {
92 	/* Note the need for a second level. */
93 	cfd_node *np = &tree[code >> (code_length - initial_bits)];
94 
95 	np->code_length = max(np->code_length, code_length);
96     }
97 }
98 
99 /* Initialize second-level nodes. */
100 private void
cfd_init2_nodes(cfd_node * tree,cfd_node * extn,uint code,int code_length,int run_length,int initial_bits)101 cfd_init2_nodes(cfd_node * tree, cfd_node * extn,
102 		uint code, int code_length, int run_length, int initial_bits)
103 {
104     int xbits = code_length - initial_bits;
105     int xrep;
106     cfd_node *np1, *np2;
107     int i;
108 
109     if (xbits <= 0)
110 	return;
111     np1 = &tree[code >> xbits];
112     np2 = &extn[np1->run_length - (1 << initial_bits)];
113     xrep = np1->code_length - code_length;
114     i = 1 << xrep;
115     np2 += (code & ((1 << xbits) - 1)) * i;
116     for (; i > 0; i--, np2++)
117 	np2->run_length = run_length,
118 	    np2->code_length = xbits;
119 }
120 
121 /* Enumerate all the relevant white or black codes. */
122 private void
cfd_enumerate_codes(cfd_node_proc proc,cfd_node * tree,cfd_node * extn,int initial_bits,const cfe_run * tt,const cfe_run * mut)123 cfd_enumerate_codes(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
124 		  int initial_bits, const cfe_run * tt, const cfe_run * mut)
125 {
126     int i;
127     const cfe_run *ep;
128 
129     for (i = 0, ep = tt; i < 64; i++, ep++)
130 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
131     for (i = 1, ep = mut + 1; i < 41; i++, ep++)
132 	(*proc) (tree, extn, ep->code, ep->code_length, i << 6, initial_bits);
133     (*proc) (tree, extn,
134 	     cf1_run_uncompressed.code, cf1_run_uncompressed.code_length,
135 	     run_uncompressed, initial_bits);
136     (*proc) (tree, extn,
137 	     0, run_eol_code_length - 1,
138 	     run_zeros, initial_bits);
139 }
140 private void
cfd_enumerate_white(cfd_node_proc proc,cfd_node * tree,cfd_node * extn,int initial_bits)141 cfd_enumerate_white(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
142 		    int initial_bits)
143 {
144     cfd_enumerate_codes(proc, tree, extn, initial_bits,
145 			cf_white_runs.termination, cf_white_runs.make_up);
146 }
147 private void
cfd_enumerate_black(cfd_node_proc proc,cfd_node * tree,cfd_node * extn,int initial_bits)148 cfd_enumerate_black(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
149 		    int initial_bits)
150 {
151     cfd_enumerate_codes(proc, tree, extn, initial_bits,
152 			cf_black_runs.termination, cf_black_runs.make_up);
153 }
154 
155 /* Enumerate the 2-D codes. */
156 private void
cfd_enumerate_2d(cfd_node_proc proc,cfd_node * tree,cfd_node * extn,int initial_bits)157 cfd_enumerate_2d(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
158 		 int initial_bits)
159 {
160     int i;
161     const cfe_run *ep;
162 
163     (*proc) (tree, extn, cf2_run_pass.code, cf2_run_pass.code_length,
164 	     run2_pass, initial_bits);
165     (*proc) (tree, extn, cf2_run_horizontal.code, cf2_run_horizontal.code_length,
166 	     run2_horizontal, initial_bits);
167     for (i = 0; i < countof(cf2_run_vertical); i++) {
168 	ep = &cf2_run_vertical[i];
169 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
170     }
171     (*proc) (tree, extn, cf2_run_uncompressed.code, cf2_run_uncompressed.code_length,
172 	     run_uncompressed, initial_bits);
173     (*proc) (tree, extn, 0, run_eol_code_length - 1, run_zeros, initial_bits);
174 }
175 
176 /* Enumerate the uncompressed codes. */
177 private void
cfd_enumerate_uncompressed(cfd_node_proc proc,cfd_node * tree,cfd_node * extn,int initial_bits)178 cfd_enumerate_uncompressed(cfd_node_proc proc, cfd_node * tree, cfd_node * extn,
179 			   int initial_bits)
180 {
181     int i;
182     const cfe_run *ep;
183 
184     for (i = 0; i < countof(cf_uncompressed); i++) {
185 	ep = &cf_uncompressed[i];
186 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
187     }
188     for (i = 0; i < countof(cf_uncompressed_exit); i++) {
189 	ep = &cf_uncompressed_exit[i];
190 	(*proc) (tree, extn, ep->code, ep->code_length, i, initial_bits);
191     }
192 }
193 
194 /* Build and write out the table. */
195 private void
cfd_build_tree(cfd_node * tree,cfd_enum_proc enum_proc,int initial_bits,FILE * f)196 cfd_build_tree(cfd_node * tree, cfd_enum_proc enum_proc, int initial_bits,
197 	       FILE * f)
198 {
199     cfd_node *np;
200     const char *prev = "";
201     int i, next;
202     cfd_node *extn;
203 
204     memset(tree, 0, sizeof(cfd_node) << initial_bits);
205     /* Construct and write the first level of the tree. */
206     (*enum_proc) (cfd_count_nodes, tree, (cfd_node *) 0, initial_bits);
207     next = 0;
208     for (i = 0, np = tree; i < 1 << initial_bits; i++, np++) {
209 	if (np->code_length > initial_bits) {	/* second level needed */
210 	    np->run_length = next + (1 << initial_bits);
211 	    next += 1 << (np->code_length - initial_bits);
212 	}
213 	fprintf(f, "%s\t{ %d, %d }", prev, np->run_length, np->code_length);
214 	prev = ",\n";
215     }
216     /* Construct and write the second level. */
217     extn = (cfd_node *) malloc(sizeof(cfd_node) * next);
218     for (i = 0, np = extn; i < next; i++, np++)
219 	np->run_length = run_error,
220 	    np->code_length = 0;
221     (*enum_proc) (cfd_init2_nodes, tree, extn, initial_bits);
222     for (i = 0, np = extn; i < next; i++, np++)
223 	fprintf(f, ",\n\t{ %d, %d }", np->run_length, np->code_length);
224     free((char *)extn);
225 }
226