ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_norm.c
Revision: 2.6
Committed: Wed Nov 13 18:20:47 2019 UTC (4 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +2 -2 lines
Log Message:
Fixed usage statement corresponding to previous addition

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.6 static const char RCSid[] = "$Id: rcode_norm.c,v 2.5 2019/11/13 18:17:05 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Encode and decode surface normal map using 32-bit integers
6     */
7    
8     #include "copyright.h"
9    
10     #include <stdlib.h>
11     #include "platform.h"
12     #include "rtio.h"
13     #include "rtmath.h"
14     #include "normcodec.h"
15    
16     char *progname; /* set in main() */
17    
18    
19     /* Report usage error and exit */
20     static void
21     usage_exit(int code)
22     {
23     fputs("Usage: ", stderr);
24     fputs(progname, stderr);
25 greg 2.6 fputs(" [-h[io]][-H[io]][-f[afd]][-x xr -y yr] [input [output.nrm]]\n", stderr);
26 greg 2.1 fputs(" Or: ", stderr);
27     fputs(progname, stderr);
28 greg 2.2 fputs(" -r [-i][-u][-h[io]][-H[io]][-f[afd]] [input.nrm [output]]\n",
29 greg 2.1 stderr);
30     exit(code);
31     }
32    
33    
34     /* Encode normals from input stream */
35     static int
36     encode_normals(NORMCODEC *ncp)
37     {
38     long nexpected = (long)ncp->res.xr * ncp->res.yr;
39    
40     if (ncp->inpfmt[0]) {
41 greg 2.3 if (strstr(ncp->inpfmt, "ascii") != NULL)
42 greg 2.1 ncp->format = 'a';
43 greg 2.3 else if (strstr(ncp->inpfmt, "float") != NULL)
44 greg 2.1 ncp->format = 'f';
45 greg 2.3 else if (strstr(ncp->inpfmt, "double") != NULL)
46 greg 2.1 ncp->format = 'd';
47     else {
48     fputs(ncp->inpname, stderr);
49     fputs(": unsupported input format: ", stderr);
50     fputs(ncp->inpfmt, stderr);
51     fputc('\n', stderr);
52     return 0;
53     }
54     }
55    
56     do {
57     int ok = 0;
58     FVECT nrm;
59    
60     switch (ncp->format) {
61     case 'a':
62     ok = (fscanf(ncp->finp, FVFORMAT,
63     &nrm[0], &nrm[1], &nrm[2]) == 3);
64     break;
65     #ifdef SMLFLT
66     case 'f':
67     ok = (getbinary(nrm, sizeof(*nrm), 3, ncp->finp) == 3);
68 greg 2.4 if (ncp->swapped)
69     swap32((char *)nrm, 3);
70 greg 2.1 break;
71     case 'd': {
72 greg 2.4 double nrmd[3];
73     ok = (getbinary(nrmd, sizeof(*nrmd),
74     3, ncp->finp) == 3);
75     if (ncp->swapped)
76     swap64((char *)nrmd, 3);
77     if (ok) VCOPY(nrm, nrmd);
78     } break;
79 greg 2.1 #else
80     case 'f': {
81 greg 2.4 float nrmf[3];
82     ok = (getbinary(nrmf, sizeof(*nrmf),
83     3, ncp->finp) == 3);
84     if (ncp->swapped)
85     swap32((char *)nrmf, 3);
86     if (ok) VCOPY(nrm, nrmf);
87     } break;
88 greg 2.1 case 'd':
89     ok = (getbinary(nrm, sizeof(*nrm), 3, ncp->finp) == 3);
90 greg 2.4 if (ncp->swapped)
91     swap64((char *)nrm, 3);
92 greg 2.1 break;
93     #endif
94     }
95     if (!ok)
96     break;
97    
98     normalize(nrm);
99     putint(encodedir(nrm), 4, stdout);
100    
101     } while (--nexpected);
102    
103     if (nexpected > 0) {
104     fputs(ncp->inpname, stderr);
105     fputs(": fewer normals than expected\n", stderr);
106     return 0;
107     }
108     return 1;
109     }
110    
111    
112     /* Output the given normal to stdout */
113     static void
114     output_normal(NORMCODEC *ncp, FVECT nrm)
115     {
116     switch (ncp->format) {
117     case 'a':
118     printf("%.9f %.9f %.9f\n", nrm[0], nrm[1], nrm[2]);
119     break;
120     #ifdef SMLFLT
121     case 'f':
122     putbinary(nrm, sizeof(*nrm), 3, stdout);
123     break;
124     case 'd': {
125     double nrmd[3];
126     VCOPY(nrmd, nrm);
127     putbinary(nrmd, sizeof(*nrmd), 3, stdout);
128     }
129     break;
130     #else
131     case 'f': {
132     float nrmf[3];
133     VCOPY(nrmf, nrm);
134     putbinary(nrmf, sizeof(*nrmf), 3, stdout);
135     }
136     break;
137     case 'd':
138     putbinary(nrm, sizeof(*nrm), 3, stdout);
139     break;
140     #endif
141     }
142     }
143    
144    
145     /* Decode normals from input stream */
146     static int
147     decode_normals(NORMCODEC *ncp)
148     {
149     long nexpected = (long)ncp->res.xr * ncp->res.yr;
150    
151     if (!check_decode_normals(ncp))
152     return 0;
153    
154     do {
155     FVECT nrm;
156    
157     if (decode_normal_next(nrm, ncp) < 0)
158     break;
159    
160     output_normal(ncp, nrm);
161    
162     } while (--nexpected);
163    
164     if (nexpected > 0) {
165     fputs(ncp->inpname, stderr);
166     fputs(": unexpected EOF\n", stderr);
167     return 0;
168     }
169     return 1;
170     }
171    
172    
173     /* Decode normals at particular pixels given on standard input */
174     static int
175     pixel_normals(NORMCODEC *ncp, int unbuf)
176     {
177     int x, y;
178     FVECT nrm;
179    
180     if (ncp->finp == stdin) {
181     fputs(progname, stderr);
182     fputs(": <stdin> used for encoded normals\n", stderr);
183     return 0;
184     }
185     if (!check_decode_normals(ncp))
186     return 0;
187     if (ncp->res.rt != PIXSTANDARD) {
188     fputs(progname, stderr);
189     fputs(": can only handle standard pixel ordering\n", stderr);
190     return 0;
191     }
192     while (scanf("%d %d", &x, &y) == 2) {
193    
194     y = ncp->res.yr-1 - y;
195    
196     if (decode_normal_pix(nrm, ncp, x, y) < 0)
197     return 0;
198    
199     output_normal(ncp, nrm);
200    
201     if (unbuf && fflush(stdout) == EOF) {
202     fputs(progname, stderr);
203     fputs(": write error on output\n", stderr);
204     return 0;
205     }
206     }
207     if (!feof(stdin)) {
208     fputs(progname, stderr);
209     fputs(": non-integer as pixel index\n", stderr);
210     return 0;
211     }
212     return 1;
213     }
214    
215    
216     int
217     main(int argc, char *argv[])
218     {
219 greg 2.5 int xres=0, yres=0;
220 greg 2.1 int reverse = 0;
221     int bypixel = 0;
222     int unbuffered = 0;
223     NORMCODEC nc;
224     int a;
225    
226     progname = argv[0];
227     set_nc_defaults(&nc);
228     nc.hdrflags = HF_ALL;
229     for (a = 1; a < argc && argv[a][0] == '-'; a++)
230     switch (argv[a][1]) {
231     case 'r':
232     reverse++;
233     break;
234     case 'f':
235     switch (argv[a][2]) {
236     case 'f':
237     case 'd':
238     case 'a':
239     nc.format = argv[a][2];
240     break;
241     default:
242     fputs(progname, stderr);
243     fputs(": unsupported -f? format\n", stderr);
244     usage_exit(1);
245     }
246     break;
247     case 'h':
248     switch (argv[a][2]) {
249     case '\0':
250     nc.hdrflags &= ~(HF_HEADIN|HF_HEADOUT);
251     break;
252     case 'i':
253     case 'I':
254     nc.hdrflags &= ~HF_HEADIN;
255     break;
256     case 'o':
257     case 'O':
258     nc.hdrflags &= ~HF_HEADOUT;
259     break;
260     default:
261     usage_exit(1);
262     }
263     break;
264     case 'H':
265     switch (argv[a][2]) {
266     case '\0':
267     nc.hdrflags &= ~(HF_RESIN|HF_RESOUT);
268     break;
269     case 'i':
270     case 'I':
271     nc.hdrflags &= ~HF_RESIN;
272     break;
273     case 'o':
274     case 'O':
275     nc.hdrflags &= ~HF_RESOUT;
276     break;
277     default:
278     usage_exit(1);
279     }
280     break;
281 greg 2.5 case 'x':
282     xres = atoi(argv[++a]);
283     break;
284     case 'y':
285     yres = atoi(argv[++a]);
286     break;
287 greg 2.1 case 'i':
288     bypixel++;
289     break;
290     case 'u':
291     unbuffered++;
292     break;
293     default:
294     usage_exit(1);
295     }
296     nc.hdrflags |= !reverse * HF_ENCODE;
297    
298 greg 2.5 if ((xres > 0) & (yres > 0)) {
299     nc.hdrflags &= ~HF_RESIN;
300     nc.res.rt = PIXSTANDARD;
301     nc.res.xr = xres;
302     nc.res.yr = yres;
303     } else if ((nc.hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESOUT) {
304 greg 2.1 fputs(progname, stderr);
305     fputs(": unknown resolution for output\n", stderr);
306     return 1;
307     }
308     if (bypixel) {
309     if (!reverse) {
310     fputs(progname, stderr);
311     fputs(": -i only supported with -r option\n",
312     stderr);
313     usage_exit(1);
314     }
315     if (a >= argc) {
316     fputs(progname, stderr);
317     fputs(": -i option requires input file\n", stderr);
318     usage_exit(1);
319     }
320     if (!(nc.hdrflags & HF_RESIN)) {
321     fputs(progname, stderr);
322     fputs(": -i option requires input resolution\n", stderr);
323     usage_exit(1);
324     }
325 greg 2.2 nc.hdrflags &= ~HF_RESOUT;
326 greg 2.1 }
327     if (a < argc-2) {
328     fputs(progname, stderr);
329     fputs(": too many file arguments\n", stderr);
330     usage_exit(1);
331     }
332     if (a < argc && !(nc.finp = fopen(nc.inpname=argv[a], "r"))) {
333     fputs(nc.inpname, stderr);
334     fputs(": cannot open for reading\n", stderr);
335     return 1;
336     }
337     if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
338     fputs(argv[a+1], stderr);
339     fputs(": cannot open for writing\n", stderr);
340     return 1;
341     }
342     SET_FILE_BINARY(nc.finp);
343     if (reverse || nc.format != 'a')
344     SET_FILE_BINARY(stdout);
345     #ifdef getc_unlocked /* avoid stupid semaphores */
346     flockfile(nc.finp);
347     flockfile(stdout);
348     #endif
349     /* read/copy header */
350     if (!process_nc_header(&nc, a, argv))
351     return 1;
352     /* process data */
353     if (!reverse) {
354     if (!encode_normals(&nc))
355     return 1;
356     } else if (bypixel) {
357     if (!pixel_normals(&nc, unbuffered))
358     return 1;
359     } else if (!decode_normals(&nc))
360     return 1;
361    
362     if (fflush(stdout) == EOF) {
363     fputs(progname, stderr);
364     fputs(": error writing output\n", stderr);
365     return 1;
366     }
367     return 0;
368     }