ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_ident.c
Revision: 2.1
Committed: Fri Jul 19 22:25:03 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Created rcode_ident file to create indexed identifier files

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * Create or read identifier index map
6     *
7     */
8    
9     #include <stdlib.h>
10     #include <ctype.h>
11     #include "rtio.h"
12     #include "platform.h"
13     #include "lookup.h"
14     #include "idmap.h"
15    
16     #ifndef MAXIDLEN
17     #define MAXIDLEN 256 /* longest ID length supported */
18     #endif
19    
20     char *progname; /* global argv[0] */
21    
22     static int unbuffered = 0;
23     static int sepc = '\n';
24    
25    
26     /* Report usage error and exit */
27     static void
28     usage_exit(int code)
29     {
30     fputs("Usage: ", stderr);
31     fputs(progname, stderr);
32     fputs(" [-8|-16|-24][-h][-tS][-x xr -y yr] [input.txt [output.idx]]\n",
33     stderr);
34     fputs(" Or: ", stderr);
35     fputs(progname, stderr);
36     fputs(" -r [-i][-u][-h][-H][-tS] input.idx [output.txt]\n", stderr);
37     exit(code);
38     }
39    
40    
41     /* read identifier from input, trimming white space on either end */
42     static int
43     scan_ident(char ident[MAXIDLEN], FILE *fp)
44     {
45     char *cp = ident;
46     int c;
47    
48     while ((c = getc(fp)) != EOF) {
49     if (cp == ident && isspace(c))
50     continue;
51     if (c == sepc) {
52     while (cp > ident && isspace(cp[-1]))
53     cp--;
54     *cp = '\0';
55     return cp - ident; /* return string length */
56     }
57     if (cp - ident >= MAXIDLEN-1) {
58     fputs(progname, stderr);
59     fputs(": identifier too long in scan_ident()\n", stderr);
60     return -1;
61     }
62     *cp++ = c;
63     }
64     return -1;
65     }
66    
67    
68     /* elide format from header lines */
69     static int
70     headline(char *s, void *p)
71     {
72     extern const char FMTSTR[];
73    
74     if (strstr(s, FMTSTR) == s)
75     return 0;
76    
77     fputs(s, stdout);
78     return 1;
79     }
80    
81    
82     /* Create an identifier index from the given input file (stdin if NULL) */
83     int
84     create_index(const char *fname, int hdrflags, int ndxbytes, int xres, int yres)
85     {
86     FILE *fp = stdin;
87     char **idmap;
88     int idmlen;
89     int nextID = 0;
90     LUTAB hashtab = LU_SINIT(free,NULL);
91     RESOLU rs;
92     long n;
93     int ndx;
94     /* open file if not stdin */
95     if (fname && !(fp = fopen(fname, "r"))) {
96     fputs(fname, stderr);
97     fputs(": cannot open for input\n", stderr);
98     return 0;
99     }
100     #ifdef getc_unlocked /* avoid stupid semaphores */
101     flockfile(fp);
102     #endif
103     /* load/copy header */
104     if (hdrflags & HF_HEADOUT && getheader(fp, headline, NULL) < 0) {
105     fputs(fname, stderr);
106     fputs(": bad header or wrong input format\n", stderr);
107     fclose(fp);
108     return 0;
109     }
110     if (!(hdrflags & HF_HEADOUT))
111     newheader("RADIANCE", stdout);
112     /* finish & allocate ID table */
113     switch (ndxbytes) {
114     case 1:
115     fputformat(IDMAP8FMT, stdout);
116     idmap = (char **)malloc((idmlen=256)*sizeof(char *));
117     break;
118     case 2:
119     fputformat(IDMAP16FMT, stdout);
120     idmap = (char **)malloc((idmlen=4096)*sizeof(char *));
121     break;
122     case 3:
123     fputformat(IDMAP24FMT, stdout);
124     idmap = (char **)malloc((idmlen=1L<<17)*sizeof(char *));
125     break;
126     default:
127     fputs(progname, stderr);
128     fputs(": unsupported bits/pixel\n", stderr);
129     return 0;
130     }
131     if (!idmap || !lu_init(&hashtab, idmlen))
132     goto memerr;
133     fputc('\n', stdout); /* end of info header */
134    
135     rs.rt = PIXSTANDARD; /* get/write map resolution */
136     if (hdrflags & HF_RESOUT) {
137     if (!fgetsresolu(&rs, fp)) {
138     fputs(fname, stderr);
139     fputs(": bad resolution string\n", stderr);
140     return 0;
141     }
142     } else if (((rs.xr = xres) <= 0) | ((rs.yr = yres) <= 0)) {
143     fputs(fname, stderr);
144     fputs(": missing/illegal resolution\n", stderr);
145     return 0;
146     }
147     fputsresolu(&rs, stdout);
148     /* read/assign/write each ID */
149     for (n = (long)rs.xr*rs.yr; n-- > 0; ) {
150     LUENT *lep;
151     char ident[MAXIDLEN];
152     int len = scan_ident(ident, fp);
153     if (len < 0) {
154     if (feof(fp)) {
155     fputs(fname, stderr);
156     fputs(": unexpected EOF\n", stderr);
157     }
158     return 0;
159     }
160     lep = lu_find(&hashtab, ident);
161     if (!lep->key) { /* new entry */
162     if (nextID >= 1<<(ndxbytes<<3)) {
163     fputs(progname, stderr);
164     fputs(
165     ": too many unique identifiers for index size\n",
166     stderr);
167     return 0;
168     }
169     if (nextID >= idmlen) { /* reallocate? */
170     idmlen += idmlen>>2; /* +25% growth */
171     idmap = (char **)realloc(idmap, idmlen);
172     if (!idmap)
173     goto memerr;
174     }
175     lep->key = (char *)malloc(len+1);
176     if (!lep->key)
177     goto memerr;
178     idmap[nextID] = strcpy(lep->key, ident);
179     lep->data = (char *)nextID++;
180     }
181     /* write this id index */
182     putint((int)lep->data, ndxbytes, stdout);
183     }
184     while ((ndx = getc(fp)) != EOF) /* verify we got them all */
185     if (!isspace(ndx)) {
186     fputs(fname, stderr);
187     fputs(": warning - non-white characters past end\n",
188     stderr);
189     break;
190     }
191     fclose(fp); /* done with input */
192     for (ndx = 0; ndx < nextID; ndx++) { /* append string table */
193     fputs(idmap[ndx], stdout);
194     putchar('\0'); /* nul-terminated IDs */
195     }
196     free(idmap); /* clean up */
197     lu_done(&hashtab);
198     return 1;
199     memerr:
200     fputs(progname, stderr);
201     fputs(": out of memory!\n", stderr);
202     return 0;
203     }
204    
205    
206     /* Load selected pixels from identifier index file */
207     int
208     decode_select(const char *fname, int hdrflags)
209     {
210     IDMAP *idmp = idmap_ropen(fname, hdrflags);
211     int x, y;
212    
213     if (!idmp)
214     return 0;
215    
216     if (idmp->res.rt != PIXSTANDARD) {
217     fputs(progname, stderr);
218     fputs(": can only handle standard pixel ordering\n", stderr);
219     idmap_close(idmp);
220     return 0;
221     }
222     while (scanf("%d %d", &x, &y) == 2) {
223     const char *id;
224    
225     if ((x < 0) | (y < 0) |
226     (x >= idmp->res.xr) | (y >= idmp->res.yr)) {
227     fputs(progname, stderr);
228     fputs(": warning - pixel index is off map\n", stderr);
229     continue;
230     }
231     y = idmp->res.yr-1 - y;
232    
233     if (!(id = idmap_pix(idmp, x, y))) {
234     idmap_close(idmp);
235     return 0;
236     }
237     fputs(id, stdout);
238     putchar(sepc);
239     if (unbuffered && fflush(stdout) == EOF) {
240     fputs(progname, stderr);
241     fputs(": write error on output\n", stderr);
242     idmap_close(idmp);
243     return 0;
244     }
245     }
246     idmap_close(idmp);
247    
248     if (!feof(stdin)) {
249     fputs(progname, stderr);
250     fputs(": non-numeric input for pixel index\n", stderr);
251     return 0;
252     }
253     return 1;
254     }
255    
256    
257     /* Load and convert identifier index file to ASCII */
258     int
259     decode_all(const char *fname, int hdrflags)
260     {
261     IDMAP *idmp = idmap_ropen(fname, hdrflags);
262     long n;
263    
264     if (!idmp)
265     return 0;
266    
267     for (n = idmp->res.xr*idmp->res.yr; n-- > 0; ) {
268     const char *id = idmap_next(idmp);
269     if (!id) {
270     fputs(fname, stderr);
271     fputs(": unexpected EOF\n", stderr);
272     idmap_close(idmp);
273     return 0;
274     }
275     fputs(id, stdout);
276     putchar(sepc);
277     }
278     idmap_close(idmp);
279     return 1;
280     }
281    
282    
283     int
284     main(int argc, char *argv[])
285     {
286     char *inpfname = NULL;
287     int reverse = 0;
288     int bypixel = 0;
289     int hdrflags = HF_HEADOUT|HF_RESOUT;
290     int xres=0, yres=0;
291     int ndxbytes = 2;
292     int a;
293    
294     progname = argv[0];
295     for (a = 1; a < argc && argv[a][0] == '-'; a++)
296     switch (argv[a][1]) {
297     case 'r':
298     reverse++;
299     break;
300     case 'i':
301     bypixel++;
302     break;
303     case 'u':
304     unbuffered++;
305     break;
306     case 'h':
307     hdrflags &= ~HF_HEADOUT;
308     break;
309     case 'H':
310     hdrflags &= ~HF_RESOUT;
311     break;
312     case 't':
313     if (!(sepc = argv[a][2]))
314     sepc = '\n';
315     break;
316     case 'x':
317     xres = atoi(argv[++a]);
318     break;
319     case 'y':
320     yres = atoi(argv[++a]);
321     break;
322     case '8':
323     case '1':
324     case '2':
325     switch (atoi(argv[a]+1)) {
326     case 8:
327     ndxbytes = 1;
328     break;
329     case 16:
330     ndxbytes = 2;
331     break;
332     case 24:
333     ndxbytes = 3;
334     break;
335     default:
336     usage_exit(1);
337     }
338     break;
339     default:
340     usage_exit(1);
341     }
342     if (reverse && a >= argc) {
343     fputs(progname, stderr);
344     fputs(": -r option requires named input file\n", stderr);
345     return 1;
346     }
347     if (a < argc-2) {
348     fputs(progname, stderr);
349     fputs(": too many file arguments\n", stderr);
350     return 1;
351     }
352     if (a < argc)
353     inpfname = argv[a];
354     if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
355     fputs(argv[a+1], stderr);
356     fputs(": cannot open output\n", stderr);
357     return 1;
358     }
359     if (!reverse)
360     SET_FILE_BINARY(stdout);
361     #ifdef getc_unlocked /* avoid stupid semaphores */
362     flockfile(stdout);
363     #endif
364     if (reverse) {
365     if (!(bypixel ? decode_select(inpfname, hdrflags) :
366     decode_all(inpfname, hdrflags)))
367     return 1;
368     } else if (!create_index(inpfname, hdrflags, ndxbytes, xres, yres))
369     return 1;
370    
371     if (fflush(stdout) == EOF) {
372     fputs(progname, stderr);
373     fputs(": error writing output\n", stderr);
374     return 1;
375     }
376     return 0;
377     }