ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_norm.c
Revision: 2.4
Committed: Wed Aug 14 21:00:14 2019 UTC (4 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +19 -13 lines
Log Message:
Added byte order to gendaymtx, rsplit, dctimestep, rcode_depth, and rcode_normal

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.4 static const char RCSid[] = "$Id: rcode_norm.c,v 2.3 2019/08/13 16:31:35 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.2 fputs(" [-h[io]][-H[io]][-f[afd]] [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     int reverse = 0;
220     int bypixel = 0;
221     int unbuffered = 0;
222     NORMCODEC nc;
223     int a;
224    
225     progname = argv[0];
226     set_nc_defaults(&nc);
227     nc.hdrflags = HF_ALL;
228     for (a = 1; a < argc && argv[a][0] == '-'; a++)
229     switch (argv[a][1]) {
230     case 'r':
231     reverse++;
232     break;
233     case 'f':
234     switch (argv[a][2]) {
235     case 'f':
236     case 'd':
237     case 'a':
238     nc.format = argv[a][2];
239     break;
240     default:
241     fputs(progname, stderr);
242     fputs(": unsupported -f? format\n", stderr);
243     usage_exit(1);
244     }
245     break;
246     case 'h':
247     switch (argv[a][2]) {
248     case '\0':
249     nc.hdrflags &= ~(HF_HEADIN|HF_HEADOUT);
250     break;
251     case 'i':
252     case 'I':
253     nc.hdrflags &= ~HF_HEADIN;
254     break;
255     case 'o':
256     case 'O':
257     nc.hdrflags &= ~HF_HEADOUT;
258     break;
259     default:
260     usage_exit(1);
261     }
262     break;
263     case 'H':
264     switch (argv[a][2]) {
265     case '\0':
266     nc.hdrflags &= ~(HF_RESIN|HF_RESOUT);
267     break;
268     case 'i':
269     case 'I':
270     nc.hdrflags &= ~HF_RESIN;
271     break;
272     case 'o':
273     case 'O':
274     nc.hdrflags &= ~HF_RESOUT;
275     break;
276     default:
277     usage_exit(1);
278     }
279     break;
280     case 'i':
281     bypixel++;
282     break;
283     case 'u':
284     unbuffered++;
285     break;
286     default:
287     usage_exit(1);
288     }
289     nc.hdrflags |= !reverse * HF_ENCODE;
290    
291     if ((nc.hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESOUT) {
292     fputs(progname, stderr);
293     fputs(": unknown resolution for output\n", stderr);
294     return 1;
295     }
296     if (bypixel) {
297     if (!reverse) {
298     fputs(progname, stderr);
299     fputs(": -i only supported with -r option\n",
300     stderr);
301     usage_exit(1);
302     }
303     if (a >= argc) {
304     fputs(progname, stderr);
305     fputs(": -i option requires input file\n", stderr);
306     usage_exit(1);
307     }
308     if (!(nc.hdrflags & HF_RESIN)) {
309     fputs(progname, stderr);
310     fputs(": -i option requires input resolution\n", stderr);
311     usage_exit(1);
312     }
313 greg 2.2 nc.hdrflags &= ~HF_RESOUT;
314 greg 2.1 }
315     if (a < argc-2) {
316     fputs(progname, stderr);
317     fputs(": too many file arguments\n", stderr);
318     usage_exit(1);
319     }
320     if (a < argc && !(nc.finp = fopen(nc.inpname=argv[a], "r"))) {
321     fputs(nc.inpname, stderr);
322     fputs(": cannot open for reading\n", stderr);
323     return 1;
324     }
325     if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
326     fputs(argv[a+1], stderr);
327     fputs(": cannot open for writing\n", stderr);
328     return 1;
329     }
330     SET_FILE_BINARY(nc.finp);
331     if (reverse || nc.format != 'a')
332     SET_FILE_BINARY(stdout);
333     #ifdef getc_unlocked /* avoid stupid semaphores */
334     flockfile(nc.finp);
335     flockfile(stdout);
336     #endif
337     /* read/copy header */
338     if (!process_nc_header(&nc, a, argv))
339     return 1;
340     /* process data */
341     if (!reverse) {
342     if (!encode_normals(&nc))
343     return 1;
344     } else if (bypixel) {
345     if (!pixel_normals(&nc, unbuffered))
346     return 1;
347     } else if (!decode_normals(&nc))
348     return 1;
349    
350     if (fflush(stdout) == EOF) {
351     fputs(progname, stderr);
352     fputs(": error writing output\n", stderr);
353     return 1;
354     }
355     return 0;
356     }