ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_norm.c
Revision: 2.11
Committed: Wed Jun 4 22:34:27 2025 UTC (2 weeks, 5 days ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.10: +2 -1 lines
Log Message:
fix: Fixed reference to fixargv0()

File Contents

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