ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_depth.c
Revision: 2.13
Committed: Tue Jun 3 21:31:51 2025 UTC (2 weeks, 4 days ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.12: +3 -5 lines
Log Message:
refactor: More consistent use of global char * progname and fixargv0()

File Contents

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