ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_depth.c
Revision: 2.11
Committed: Mon Jul 20 15:53:30 2020 UTC (3 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.10: +9 -5 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_depth.c,v 2.10 2020/02/12 01:13:01 greg Exp $";
3 #endif
4 /*
5 * Encode and decode depth map using 16-bit integers
6 */
7
8 #include "copyright.h"
9
10 #include <stdlib.h>
11 #include <math.h>
12 #include <ctype.h>
13 #include "platform.h"
14 #include "rtio.h"
15 #include "fvect.h"
16 #include "depthcodec.h"
17
18 char *progname; /* set in main() */
19
20 enum {CV_FWD, CV_REV, CV_PTS};
21
22
23 /* Report usage error and exit */
24 static void
25 usage_exit(int code)
26 {
27 fputs("Usage: ", stderr);
28 fputs(progname, stderr);
29 fputs(
30 " [-d ref_depth/unit][-h[io]][-H[io]][-f[afd]][-x xr -y yr] [input [output.dpt]]\n",
31 stderr);
32 fputs(" Or: ", stderr);
33 fputs(progname, stderr);
34 fputs(
35 " {-r|-p} [-i][-u][-h[io]][-H[io]][-f[afd]] [input.dpt [output]]\n",
36 stderr);
37 exit(code);
38 }
39
40
41 /* Encode depths from input stream */
42 static int
43 encode_depths(DEPTHCODEC *dcp)
44 {
45 long nexpected = (long)dcp->res.xr * dcp->res.yr;
46
47 if (dcp->inpfmt[0]) {
48 if (!strcmp(dcp->inpfmt, "ascii"))
49 dcp->format = 'a';
50 else if (!strcmp(dcp->inpfmt, "float"))
51 dcp->format = 'f';
52 else if (!strcmp(dcp->inpfmt, "double"))
53 dcp->format = 'd';
54 else {
55 fputs(dcp->inpname, stderr);
56 fputs(": unsupported input format: ", stderr);
57 fputs(dcp->inpfmt, stderr);
58 fputc('\n', stderr);
59 return 0;
60 }
61 }
62 if (dcp->format == 'a')
63 SET_FILE_TEXT(dcp->finp);
64
65 do {
66 int ok = 0;
67 float f;
68 double d;
69
70 switch (dcp->format) {
71 case 'a':
72 ok = (fscanf(dcp->finp, "%lf", &d) == 1);
73 break;
74 case 'f':
75 ok = (getbinary(&f, sizeof(f), 1, dcp->finp) == 1);
76 if (dcp->swapped)
77 swap32((char *)&f, 1);
78 d = f;
79 break;
80 case 'd':
81 ok = (getbinary(&d, sizeof(d), 1, dcp->finp) == 1);
82 if (dcp->swapped)
83 swap64((char *)&d, 1);
84 break;
85 }
86 if (!ok)
87 break;
88
89 putint(depth2code(d, dcp->refdepth), 2, stdout);
90
91 } while (--nexpected);
92
93 if (nexpected > 0) {
94 fputs(dcp->inpname, stderr);
95 fputs(": fewer depths than expected\n", stderr);
96 return 0;
97 }
98 return 1;
99 }
100
101
102 /* Convert and output the given depth to stdout */
103 static void
104 output_depth(DEPTHCODEC *dcp, double d)
105 {
106 float f;
107
108 switch (dcp->format) {
109 case 'a':
110 printf("%.5e\n", d);
111 break;
112 case 'f':
113 f = d;
114 putbinary(&f, sizeof(f), 1, stdout);
115 break;
116 case 'd':
117 putbinary(&d, sizeof(d), 1, stdout);
118 break;
119 }
120 }
121
122
123 /* Decode depths from input stream */
124 static int
125 decode_depths(DEPTHCODEC *dcp)
126 {
127 long nexpected = (long)dcp->res.xr * dcp->res.yr;
128
129 if (!check_decode_depths(dcp))
130 return 0;
131
132 do {
133 double d = decode_depth_next(dcp);
134 if (d < -FTINY)
135 break;
136 output_depth(dcp, d);
137
138 } while (--nexpected);
139
140 if (nexpected > 0) {
141 fputs(dcp->inpname, stderr);
142 fputs(": unexpected EOF\n", stderr);
143 return 0;
144 }
145 return 1;
146 }
147
148
149 /* Decode depths at particular pixels given on standard input */
150 static int
151 pixel_depths(DEPTHCODEC *dcp, int unbuf)
152 {
153 int xy[2];
154 double d;
155
156 if (dcp->finp == stdin) {
157 fputs(progname, stderr);
158 fputs(": <stdin> used for encoded depths\n", stderr);
159 return 0;
160 }
161 if (!check_decode_depths(dcp))
162 return 0;
163
164 while (scanf("%d %d", &xy[0], &xy[1]) == 2) {
165
166 loc2pix(xy, &dcp->res,
167 (xy[0]+.5)/dcp->res.xr, (xy[1]+.5)/dcp->res.yr);
168
169 d = decode_depth_pix(dcp, xy[0], xy[1]);
170 if (d < -FTINY)
171 return 0;
172
173 output_depth(dcp, d);
174
175 if (unbuf && fflush(stdout) == EOF) {
176 fputs(progname, stderr);
177 fputs(": write error on output\n", stderr);
178 return 0;
179 }
180 }
181 if (!feof(stdin)) {
182 fputs(progname, stderr);
183 fputs(": non-integer as pixel index\n", stderr);
184 return 0;
185 }
186 return 1;
187 }
188
189
190 /* Output the given world position to stdout */
191 static void
192 output_worldpos(DEPTHCODEC *dcp, FVECT wpos)
193 {
194 switch (dcp->format) {
195 case 'a':
196 printf("%.5e %.5e %.5e\n", wpos[0], wpos[1], wpos[2]);
197 break;
198 #ifdef SMLFLT
199 case 'f':
200 putbinary(wpos, sizeof(*wpos), 3, stdout);
201 break;
202 case 'd': {
203 double wpd[3];
204 VCOPY(wpd, wpos);
205 putbinary(wpd, sizeof(*wpd), 3, stdout);
206 }
207 break;
208 #else
209 case 'f': {
210 float wpf[3];
211 VCOPY(wpf, wpos);
212 putbinary(wpf, sizeof(*wpf), 3, stdout);
213 }
214 break;
215 case 'd':
216 putbinary(wpos, sizeof(*wpos), 3, stdout);
217 break;
218 #endif
219 }
220 }
221
222
223 /* Decode world points from input stream */
224 static int
225 decode_points(DEPTHCODEC *dcp)
226 {
227 long n = (long)dcp->res.xr * dcp->res.yr;
228
229 if (!check_decode_worldpos(dcp))
230 return 0;
231
232 while (n-- > 0) {
233 FVECT wpos;
234 if (decode_worldpos_next(wpos, dcp) < 0) {
235 if (feof(dcp->finp)) {
236 fputs(dcp->inpname, stderr);
237 fputs(": unexpected EOF\n", stderr);
238 }
239 return 0;
240 }
241 output_worldpos(dcp, wpos);
242 }
243 return 1;
244 }
245
246
247 /* Decode world points at particular pixels given on standard input */
248 static int
249 pixel_points(DEPTHCODEC *dcp, int unbuf)
250 {
251 int xy[2];
252 FVECT wpos;
253
254 if (dcp->finp == stdin) {
255 fputs(progname, stderr);
256 fputs(": <stdin> used for encoded depths\n", stderr);
257 return 0;
258 }
259 if (!check_decode_worldpos(dcp))
260 return 0;
261
262 while (scanf("%d %d", &xy[0], &xy[1]) == 2) {
263 loc2pix(xy, &dcp->res,
264 (xy[0]+.5)/dcp->res.xr, (xy[1]+.5)/dcp->res.yr);
265 if (get_worldpos_pix(wpos, dcp, xy[0], xy[1]) < 0)
266 return 0;
267 output_worldpos(dcp, wpos);
268 if (unbuf && fflush(stdout) == EOF) {
269 fputs(progname, stderr);
270 fputs(": write error on output\n", stderr);
271 return 0;
272 }
273 }
274 if (!feof(stdin)) {
275 fputs(progname, stderr);
276 fputs(": non-integer as pixel index\n", stderr);
277 return 0;
278 }
279 return 1;
280 }
281
282
283 int
284 main(int argc, char *argv[])
285 {
286 int xres=0, yres=0;
287 int conversion = CV_FWD;
288 int bypixel = 0;
289 int unbuffered = 0;
290 DEPTHCODEC dc;
291 int a;
292
293 progname = argv[0];
294 set_dc_defaults(&dc);
295 dc.hdrflags = HF_ALL;
296 for (a = 1; a < argc && argv[a][0] == '-'; a++)
297 switch (argv[a][1]) {
298 case 'd':
299 strlcpy(dc.depth_unit, argv[++a], sizeof(dc.depth_unit));
300 dc.refdepth = atof(dc.depth_unit);
301 if (dc.refdepth <= .0) {
302 fputs(progname, stderr);
303 fputs(": illegal -d reference depth\n", stderr);
304 return 1;
305 }
306 break;
307 case 'r':
308 conversion = CV_REV;
309 break;
310 case 'p':
311 conversion = CV_PTS;
312 break;
313 case 'f':
314 switch (argv[a][2]) {
315 case 'f':
316 case 'd':
317 case 'a':
318 dc.format = argv[a][2];
319 break;
320 default:
321 fputs(progname, stderr);
322 fputs(": unsupported -f? format\n", stderr);
323 usage_exit(1);
324 }
325 break;
326 case 'h':
327 switch (argv[a][2]) {
328 case '\0':
329 dc.hdrflags &= ~(HF_HEADIN|HF_HEADOUT);
330 break;
331 case 'i':
332 case 'I':
333 dc.hdrflags &= ~HF_HEADIN;
334 break;
335 case 'o':
336 case 'O':
337 dc.hdrflags &= ~HF_HEADOUT;
338 break;
339 default:
340 usage_exit(1);
341 }
342 break;
343 case 'H':
344 switch (argv[a][2]) {
345 case '\0':
346 dc.hdrflags &= ~(HF_RESIN|HF_RESOUT);
347 break;
348 case 'i':
349 case 'I':
350 dc.hdrflags &= ~HF_RESIN;
351 break;
352 case 'o':
353 case 'O':
354 dc.hdrflags &= ~HF_RESOUT;
355 break;
356 default:
357 usage_exit(1);
358 }
359 break;
360 case 'x':
361 xres = atoi(argv[++a]);
362 break;
363 case 'y':
364 yres = atoi(argv[++a]);
365 break;
366 case 'i':
367 bypixel++;
368 break;
369 case 'u':
370 unbuffered++;
371 break;
372 default:
373 usage_exit(1);
374 }
375 dc.hdrflags |= (conversion == CV_FWD) * HF_ENCODE;
376
377 if ((xres > 0) & (yres > 0)) {
378 dc.hdrflags &= ~HF_RESIN;
379 dc.res.rt = PIXSTANDARD;
380 dc.res.xr = xres;
381 dc.res.yr = yres;
382 } else if ((dc.hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESOUT) {
383 fputs(progname, stderr);
384 fputs(": unknown resolution for output\n", stderr);
385 return 1;
386 }
387 if (bypixel) {
388 if (conversion == CV_FWD) {
389 fputs(progname, stderr);
390 fputs(": -i only supported with -r or -p option\n",
391 stderr);
392 usage_exit(1);
393 }
394 if (a >= argc) {
395 fputs(progname, stderr);
396 fputs(": -i option requires input file\n", stderr);
397 usage_exit(1);
398 }
399 if (!(dc.hdrflags & HF_RESIN)) {
400 fputs(progname, stderr);
401 fputs(": -i option requires input resolution\n", stderr);
402 usage_exit(1);
403 }
404 dc.hdrflags &= ~HF_RESOUT;
405 }
406 if (a < argc-2) {
407 fputs(progname, stderr);
408 fputs(": too many file arguments\n", stderr);
409 usage_exit(1);
410 }
411 if (a < argc && !(dc.finp = fopen(dc.inpname=argv[a], "r"))) {
412 fputs(dc.inpname, stderr);
413 fputs(": cannot open for reading\n", stderr);
414 return 1;
415 }
416 if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
417 fputs(argv[a+1], stderr);
418 fputs(": cannot open for writing\n", stderr);
419 return 1;
420 }
421 SET_FILE_BINARY(dc.finp); /* starting assumption */
422 SET_FILE_BINARY(stdout);
423 #ifdef getc_unlocked /* avoid stupid semaphores */
424 flockfile(dc.finp);
425 flockfile(stdout);
426 #endif
427 /* read/copy header */
428 if (!process_dc_header(&dc, a, argv))
429 return 1;
430
431 if ((conversion != CV_FWD) & (dc.format == 'a'))
432 SET_FILE_TEXT(stdout);
433 /* process data */
434 switch (conversion) {
435 case CV_FWD: /* distance -> depth code */
436 if (!strcmp(dc.depth_unit, "1")) {
437 fputs(progname, stderr);
438 fputs(": warning - using reference depth of 1.0\n",
439 stderr);
440 }
441 if (!encode_depths(&dc))
442 return 1;
443 break;
444 case CV_REV: /* depth code -> distance */
445 if (!(bypixel ? pixel_depths(&dc, unbuffered) :
446 decode_depths(&dc)))
447 return 1;
448 break;
449 case CV_PTS: /* depth code -> world points */
450 if (!(bypixel ? pixel_points(&dc, unbuffered) :
451 decode_points(&dc)))
452 return 1;
453 break;
454 }
455 if (fflush(stdout) == EOF) {
456 fputs(progname, stderr);
457 fputs(": error writing output\n", stderr);
458 return 1;
459 }
460 return 0;
461 }