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, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Created rcode_ident file to create indexed identifier files

File Contents

# Content
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 }