ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_norm.c
Revision: 2.9
Committed: Fri Jul 24 16:00:10 2020 UTC (3 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R3, HEAD
Changes since 2.8: +2 -2 lines
Log Message:
fix(rcode_norm): typo in change for Windows

File Contents

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