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, 4 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_norm.c,v 2.5 2019/11/13 18:17:05 greg Exp $";
3 #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 fputs(" [-h[io]][-H[io]][-f[afd]][-x xr -y yr] [input [output.nrm]]\n", stderr);
26 fputs(" Or: ", stderr);
27 fputs(progname, stderr);
28 fputs(" -r [-i][-u][-h[io]][-H[io]][-f[afd]] [input.nrm [output]]\n",
29 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 if (strstr(ncp->inpfmt, "ascii") != NULL)
42 ncp->format = 'a';
43 else if (strstr(ncp->inpfmt, "float") != NULL)
44 ncp->format = 'f';
45 else if (strstr(ncp->inpfmt, "double") != NULL)
46 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 if (ncp->swapped)
69 swap32((char *)nrm, 3);
70 break;
71 case 'd': {
72 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 #else
80 case 'f': {
81 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 case 'd':
89 ok = (getbinary(nrm, sizeof(*nrm), 3, ncp->finp) == 3);
90 if (ncp->swapped)
91 swap64((char *)nrm, 3);
92 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 xres=0, yres=0;
220 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 case 'x':
282 xres = atoi(argv[++a]);
283 break;
284 case 'y':
285 yres = atoi(argv[++a]);
286 break;
287 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 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 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 nc.hdrflags &= ~HF_RESOUT;
326 }
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 }