ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_depth.c
Revision: 2.2
Committed: Thu Jul 18 19:13:44 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +2 -2 lines
Log Message:
Following convention of leaving file names off in header command line detail

File Contents

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