ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_ident.c
Revision: 2.2
Committed: Fri Jul 19 22:57:12 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +8 -3 lines
Log Message:
Fixed issue with -x and -y option still expecting resolution string

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_ident.c,v 2.1 2019/07/19 22:25:03 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 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)
96 fname = "<stdin>";
97 else if (!(fp = fopen(fname, "r"))) {
98 fputs(fname, stderr);
99 fputs(": cannot open for input\n", stderr);
100 return 0;
101 }
102 #ifdef getc_unlocked /* avoid stupid semaphores */
103 flockfile(fp);
104 #endif
105 /* load/copy header */
106 if (hdrflags & HF_HEADOUT && getheader(fp, headline, NULL) < 0) {
107 fputs(fname, stderr);
108 fputs(": bad header or wrong input format\n", stderr);
109 fclose(fp);
110 return 0;
111 }
112 if (!(hdrflags & HF_HEADOUT))
113 newheader("RADIANCE", stdout);
114 /* finish & allocate ID table */
115 switch (ndxbytes) {
116 case 1:
117 fputformat(IDMAP8FMT, stdout);
118 idmap = (char **)malloc((idmlen=256)*sizeof(char *));
119 break;
120 case 2:
121 fputformat(IDMAP16FMT, stdout);
122 idmap = (char **)malloc((idmlen=4096)*sizeof(char *));
123 break;
124 case 3:
125 fputformat(IDMAP24FMT, stdout);
126 idmap = (char **)malloc((idmlen=1L<<17)*sizeof(char *));
127 break;
128 default:
129 fputs(progname, stderr);
130 fputs(": unsupported bits/pixel\n", stderr);
131 return 0;
132 }
133 if (!idmap || !lu_init(&hashtab, idmlen))
134 goto memerr;
135 fputc('\n', stdout); /* end of info header */
136
137 rs.rt = PIXSTANDARD; /* get/write map resolution */
138 if (hdrflags & HF_RESOUT) {
139 if (!fgetsresolu(&rs, fp)) {
140 fputs(fname, stderr);
141 fputs(": bad resolution string\n", stderr);
142 return 0;
143 }
144 } else if (((rs.xr = xres) <= 0) | ((rs.yr = yres) <= 0)) {
145 fputs(fname, stderr);
146 fputs(": missing/illegal resolution\n", stderr);
147 return 0;
148 }
149 fputsresolu(&rs, stdout);
150 /* read/assign/write each ID */
151 for (n = (long)rs.xr*rs.yr; n-- > 0; ) {
152 LUENT *lep;
153 char ident[MAXIDLEN];
154 int len = scan_ident(ident, fp);
155 if (len < 0) {
156 if (feof(fp)) {
157 fputs(fname, stderr);
158 fputs(": unexpected EOF\n", stderr);
159 }
160 return 0;
161 }
162 lep = lu_find(&hashtab, ident);
163 if (!lep->key) { /* new entry */
164 if (nextID >= 1<<(ndxbytes<<3)) {
165 fputs(progname, stderr);
166 fputs(
167 ": too many unique identifiers for index size\n",
168 stderr);
169 return 0;
170 }
171 if (nextID >= idmlen) { /* reallocate? */
172 idmlen += idmlen>>2; /* +25% growth */
173 idmap = (char **)realloc(idmap, idmlen);
174 if (!idmap)
175 goto memerr;
176 }
177 lep->key = (char *)malloc(len+1);
178 if (!lep->key)
179 goto memerr;
180 idmap[nextID] = strcpy(lep->key, ident);
181 lep->data = (char *)nextID++;
182 }
183 /* write this id index */
184 putint((int)lep->data, ndxbytes, stdout);
185 }
186 while ((ndx = getc(fp)) != EOF) /* verify we got them all */
187 if (!isspace(ndx)) {
188 fputs(fname, stderr);
189 fputs(": warning - non-white characters past end\n",
190 stderr);
191 break;
192 }
193 if (fp != stdin) /* done with input */
194 fclose(fp);
195 for (ndx = 0; ndx < nextID; ndx++) { /* append string table */
196 fputs(idmap[ndx], stdout);
197 putchar('\0'); /* nul-terminated IDs */
198 }
199 free(idmap); /* clean up */
200 lu_done(&hashtab);
201 return 1;
202 memerr:
203 fputs(progname, stderr);
204 fputs(": out of memory!\n", stderr);
205 return 0;
206 }
207
208
209 /* Load selected pixels from identifier index file */
210 int
211 decode_select(const char *fname, int hdrflags)
212 {
213 IDMAP *idmp = idmap_ropen(fname, hdrflags);
214 int x, y;
215
216 if (!idmp)
217 return 0;
218
219 if (idmp->res.rt != PIXSTANDARD) {
220 fputs(progname, stderr);
221 fputs(": can only handle standard pixel ordering\n", stderr);
222 idmap_close(idmp);
223 return 0;
224 }
225 while (scanf("%d %d", &x, &y) == 2) {
226 const char *id;
227
228 if ((x < 0) | (y < 0) |
229 (x >= idmp->res.xr) | (y >= idmp->res.yr)) {
230 fputs(progname, stderr);
231 fputs(": warning - pixel index is off map\n", stderr);
232 continue;
233 }
234 y = idmp->res.yr-1 - y;
235
236 if (!(id = idmap_pix(idmp, x, y))) {
237 idmap_close(idmp);
238 return 0;
239 }
240 fputs(id, stdout);
241 putchar(sepc);
242 if (unbuffered && fflush(stdout) == EOF) {
243 fputs(progname, stderr);
244 fputs(": write error on output\n", stderr);
245 idmap_close(idmp);
246 return 0;
247 }
248 }
249 idmap_close(idmp);
250
251 if (!feof(stdin)) {
252 fputs(progname, stderr);
253 fputs(": non-numeric input for pixel index\n", stderr);
254 return 0;
255 }
256 return 1;
257 }
258
259
260 /* Load and convert identifier index file to ASCII */
261 int
262 decode_all(const char *fname, int hdrflags)
263 {
264 IDMAP *idmp = idmap_ropen(fname, hdrflags);
265 long n;
266
267 if (!idmp)
268 return 0;
269
270 for (n = idmp->res.xr*idmp->res.yr; n-- > 0; ) {
271 const char *id = idmap_next(idmp);
272 if (!id) {
273 fputs(fname, stderr);
274 fputs(": unexpected EOF\n", stderr);
275 idmap_close(idmp);
276 return 0;
277 }
278 fputs(id, stdout);
279 putchar(sepc);
280 }
281 idmap_close(idmp);
282 return 1;
283 }
284
285
286 int
287 main(int argc, char *argv[])
288 {
289 char *inpfname = NULL;
290 int reverse = 0;
291 int bypixel = 0;
292 int hdrflags = HF_HEADOUT|HF_RESOUT;
293 int xres=0, yres=0;
294 int ndxbytes = 2;
295 int a;
296
297 progname = argv[0];
298 for (a = 1; a < argc && argv[a][0] == '-'; a++)
299 switch (argv[a][1]) {
300 case 'r':
301 reverse++;
302 break;
303 case 'i':
304 bypixel++;
305 break;
306 case 'u':
307 unbuffered++;
308 break;
309 case 'h':
310 hdrflags &= ~HF_HEADOUT;
311 break;
312 case 'H':
313 hdrflags &= ~HF_RESOUT;
314 break;
315 case 't':
316 if (!(sepc = argv[a][2]))
317 sepc = '\n';
318 break;
319 case 'x':
320 xres = atoi(argv[++a]);
321 break;
322 case 'y':
323 yres = atoi(argv[++a]);
324 break;
325 case '8':
326 case '1':
327 case '2':
328 switch (atoi(argv[a]+1)) {
329 case 8:
330 ndxbytes = 1;
331 break;
332 case 16:
333 ndxbytes = 2;
334 break;
335 case 24:
336 ndxbytes = 3;
337 break;
338 default:
339 usage_exit(1);
340 }
341 break;
342 default:
343 usage_exit(1);
344 }
345 if ((xres > 0) & (yres > 0)) /* user specified resolution? */
346 hdrflags &= ~HF_RESOUT;
347 if (reverse && a >= argc) {
348 fputs(progname, stderr);
349 fputs(": -r option requires named input file\n", stderr);
350 return 1;
351 }
352 if (a < argc-2) {
353 fputs(progname, stderr);
354 fputs(": too many file arguments\n", stderr);
355 return 1;
356 }
357 if (a < argc)
358 inpfname = argv[a];
359 if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
360 fputs(argv[a+1], stderr);
361 fputs(": cannot open output\n", stderr);
362 return 1;
363 }
364 if (!reverse)
365 SET_FILE_BINARY(stdout);
366 #ifdef getc_unlocked /* avoid stupid semaphores */
367 flockfile(stdout);
368 #endif
369 if (reverse) {
370 if (!(bypixel ? decode_select(inpfname, hdrflags) :
371 decode_all(inpfname, hdrflags)))
372 return 1;
373 } else if (!create_index(inpfname, hdrflags, ndxbytes, xres, yres))
374 return 1;
375
376 if (fflush(stdout) == EOF) {
377 fputs(progname, stderr);
378 fputs(": error writing output\n", stderr);
379 return 1;
380 }
381 return 0;
382 }