ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_norm.c
Revision: 2.3
Committed: Tue Aug 13 16:31:35 2019 UTC (4 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +4 -4 lines
Log Message:
Windows cleaning (thanks to Nathaniel Jones for pointing out errors)

File Contents

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