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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_ident.c,v 2.7 2019/07/24 17:50:32 greg Exp $";
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 #define HF_TABLOUT 0x100 /* output ID table after header */
21
22 char *progname; /* global argv[0] */
23
24 static int unbuffered = 0;
25 static int numeric = 0;
26 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 fputs(" -r [-i][-u][-h][-H][-l][-n][-tS] input.idx [output.txt]\n",
40 stderr);
41 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 if (isformat(s))
77 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 LUTAB hashtab;
93 RESOLU rs;
94 long n;
95 int ndx;
96 /* open file if not stdin */
97 if (!fname)
98 fname = "<stdin>";
99 else if (!(fp = fopen(fname, "r"))) {
100 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 memset(&hashtab, 0, sizeof(hashtab));
136 hashtab.hashf = lu_shash;
137 hashtab.keycmp = strcmp;
138 hashtab.freek = free;
139 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 if (fp != stdin) /* done with input */
200 fclose(fp);
201 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 /* print out ID table */
216 void
217 print_IDs(IDMAP *idmp)
218 {
219 int i;
220
221 printf("============ %d IDs ============\n", idmp->nids);
222
223 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 puts("============= END =============");
230 }
231
232
233 /* 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 int i, j;
239
240 if (!idmp)
241 return 0;
242
243 if (hdrflags & HF_TABLOUT)
244 print_IDs(idmp);
245
246 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 while (scanf("%d %d", &i, &j) == 2) {
253 i = idmap_seek(idmp, i, idmp->res.yr-1 - j);
254 if (!i) {
255 fputs(progname, stderr);
256 fputs(": warning - pixel index is off map\n", stderr);
257 continue;
258 }
259 if (i > 0)
260 i = idmap_next_i(idmp);
261 if (i < 0) {
262 fputs(fname, stderr);
263 fputs(": read/seek error in decode_select()\n", stderr);
264 idmap_close(idmp);
265 return 0;
266 }
267 if (numeric) {
268 printf("%d", i);
269 } else {
270 const char *id = mapID(idmp, i);
271 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 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 if (hdrflags & HF_TABLOUT)
309 print_IDs(idmp);
310
311 for (n = idmp->res.xr*idmp->res.yr; n-- > 0; ) {
312 const int ndx = idmap_next_i(idmp);
313 if (ndx < 0) {
314 fputs(fname, stderr);
315 fputs(": unexpected EOF\n", stderr);
316 idmap_close(idmp);
317 return 0;
318 }
319 if (numeric) {
320 printf("%d", ndx);
321 } else {
322 const char *id = mapID(idmp, ndx);
323 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 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 case 'n':
362 numeric++;
363 break;
364 case 'l':
365 hdrflags |= HF_TABLOUT;
366 break;
367 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 if ((xres > 0) & (yres > 0)) /* user specified resolution? */
404 hdrflags &= ~HF_RESOUT;
405 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 }