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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_norm.c,v 2.3 2019/08/13 16:31:35 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 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 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 nc.hdrflags &= ~HF_RESOUT;
314 }
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 }