ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_norm.c
Revision: 2.8
Committed: Mon Jul 20 15:53:30 2020 UTC (3 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.7: +9 -4 lines
Log Message:
fix(rcode_depth, rcode_norm): TEXT/BINARY mode was mishandled for Windows

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_norm.c,v 2.7 2020/02/12 01:13:01 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 (!strcmp(ncp->inpfmt, "ascii"))
42 ncp->format = 'a';
43 else if (!strcmp(ncp->inpfmt, "float"))
44 ncp->format = 'f';
45 else if (!strcmp(ncp->inpfmt, "double"))
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 if (ncp->format == 'a')
56 SET_FILE_TEXT(ncp->finp);
57
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 if (ncp->swapped)
71 swap32((char *)nrm, 3);
72 break;
73 case 'd': {
74 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 #else
82 case 'f': {
83 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 case 'd':
91 ok = (getbinary(nrm, sizeof(*nrm), 3, ncp->finp) == 3);
92 if (ncp->swapped)
93 swap64((char *)nrm, 3);
94 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
195 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 int xres=0, yres=0;
223 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 case 'x':
285 xres = atoi(argv[++a]);
286 break;
287 case 'y':
288 yres = atoi(argv[++a]);
289 break;
290 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 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 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 nc.hdrflags &= ~HF_RESOUT;
329 }
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 SET_FILE_BINARY(dc.finp); /* starting assumption */
346 SET_FILE_BINARY(stdout);
347 #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
355 if (reverse && nc.format == 'a')
356 SET_FILE_TEXT(stdout);
357 /* 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 }