ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_ident.c
Revision: 2.8
Committed: Fri Jul 26 17:45:23 2019 UTC (4 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.7: +2 -4 lines
Log Message:
Switched to more standard method of detecting format line

File Contents

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