ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_depth.c
Revision: 2.12
Committed: Thu Jun 30 00:16:49 2022 UTC (3 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.11: +5 -9 lines
Log Message:
fix(rcode_depth): Pixels with -i option were off by 1

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_depth.c,v 2.11 2020/07/20 15:53:30 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 loc2pix(xy, &dcp->res, xy[0]/(double)dcp->res.xr,
166 xy[1]/(double)dcp->res.yr);
167 d = decode_depth_pix(dcp, xy[0], xy[1]);
168 if (d < -FTINY)
169 return 0;
170 output_depth(dcp, d);
171 if (unbuf && fflush(stdout) == EOF) {
172 fputs(progname, stderr);
173 fputs(": write error on output\n", stderr);
174 return 0;
175 }
176 }
177 if (!feof(stdin)) {
178 fputs(progname, stderr);
179 fputs(": non-integer as pixel index\n", stderr);
180 return 0;
181 }
182 return 1;
183 }
184
185
186 /* Output the given world position to stdout */
187 static void
188 output_worldpos(DEPTHCODEC *dcp, FVECT wpos)
189 {
190 switch (dcp->format) {
191 case 'a':
192 printf("%.5e %.5e %.5e\n", wpos[0], wpos[1], wpos[2]);
193 break;
194 #ifdef SMLFLT
195 case 'f':
196 putbinary(wpos, sizeof(*wpos), 3, stdout);
197 break;
198 case 'd': {
199 double wpd[3];
200 VCOPY(wpd, wpos);
201 putbinary(wpd, sizeof(*wpd), 3, stdout);
202 }
203 break;
204 #else
205 case 'f': {
206 float wpf[3];
207 VCOPY(wpf, wpos);
208 putbinary(wpf, sizeof(*wpf), 3, stdout);
209 }
210 break;
211 case 'd':
212 putbinary(wpos, sizeof(*wpos), 3, stdout);
213 break;
214 #endif
215 }
216 }
217
218
219 /* Decode world points from input stream */
220 static int
221 decode_points(DEPTHCODEC *dcp)
222 {
223 long n = (long)dcp->res.xr * dcp->res.yr;
224
225 if (!check_decode_worldpos(dcp))
226 return 0;
227
228 while (n-- > 0) {
229 FVECT wpos;
230 if (decode_worldpos_next(wpos, dcp) < 0) {
231 if (feof(dcp->finp)) {
232 fputs(dcp->inpname, stderr);
233 fputs(": unexpected EOF\n", stderr);
234 }
235 return 0;
236 }
237 output_worldpos(dcp, wpos);
238 }
239 return 1;
240 }
241
242
243 /* Decode world points at particular pixels given on standard input */
244 static int
245 pixel_points(DEPTHCODEC *dcp, int unbuf)
246 {
247 int xy[2];
248 FVECT wpos;
249
250 if (dcp->finp == stdin) {
251 fputs(progname, stderr);
252 fputs(": <stdin> used for encoded depths\n", stderr);
253 return 0;
254 }
255 if (!check_decode_worldpos(dcp))
256 return 0;
257
258 while (scanf("%d %d", &xy[0], &xy[1]) == 2) {
259 loc2pix(xy, &dcp->res, xy[0]/(double)dcp->res.xr,
260 xy[1]/(double)dcp->res.yr);
261 if (get_worldpos_pix(wpos, dcp, xy[0], xy[1]) < 0)
262 return 0;
263 output_worldpos(dcp, wpos);
264 if (unbuf && fflush(stdout) == EOF) {
265 fputs(progname, stderr);
266 fputs(": write error on output\n", stderr);
267 return 0;
268 }
269 }
270 if (!feof(stdin)) {
271 fputs(progname, stderr);
272 fputs(": non-integer as pixel index\n", stderr);
273 return 0;
274 }
275 return 1;
276 }
277
278
279 int
280 main(int argc, char *argv[])
281 {
282 int xres=0, yres=0;
283 int conversion = CV_FWD;
284 int bypixel = 0;
285 int unbuffered = 0;
286 DEPTHCODEC dc;
287 int a;
288
289 progname = argv[0];
290 set_dc_defaults(&dc);
291 dc.hdrflags = HF_ALL;
292 for (a = 1; a < argc && argv[a][0] == '-'; a++)
293 switch (argv[a][1]) {
294 case 'd':
295 strlcpy(dc.depth_unit, argv[++a], sizeof(dc.depth_unit));
296 dc.refdepth = atof(dc.depth_unit);
297 if (dc.refdepth <= .0) {
298 fputs(progname, stderr);
299 fputs(": illegal -d reference depth\n", stderr);
300 return 1;
301 }
302 break;
303 case 'r':
304 conversion = CV_REV;
305 break;
306 case 'p':
307 conversion = CV_PTS;
308 break;
309 case 'f':
310 switch (argv[a][2]) {
311 case 'f':
312 case 'd':
313 case 'a':
314 dc.format = argv[a][2];
315 break;
316 default:
317 fputs(progname, stderr);
318 fputs(": unsupported -f? format\n", stderr);
319 usage_exit(1);
320 }
321 break;
322 case 'h':
323 switch (argv[a][2]) {
324 case '\0':
325 dc.hdrflags &= ~(HF_HEADIN|HF_HEADOUT);
326 break;
327 case 'i':
328 case 'I':
329 dc.hdrflags &= ~HF_HEADIN;
330 break;
331 case 'o':
332 case 'O':
333 dc.hdrflags &= ~HF_HEADOUT;
334 break;
335 default:
336 usage_exit(1);
337 }
338 break;
339 case 'H':
340 switch (argv[a][2]) {
341 case '\0':
342 dc.hdrflags &= ~(HF_RESIN|HF_RESOUT);
343 break;
344 case 'i':
345 case 'I':
346 dc.hdrflags &= ~HF_RESIN;
347 break;
348 case 'o':
349 case 'O':
350 dc.hdrflags &= ~HF_RESOUT;
351 break;
352 default:
353 usage_exit(1);
354 }
355 break;
356 case 'x':
357 xres = atoi(argv[++a]);
358 break;
359 case 'y':
360 yres = atoi(argv[++a]);
361 break;
362 case 'i':
363 bypixel++;
364 break;
365 case 'u':
366 unbuffered++;
367 break;
368 default:
369 usage_exit(1);
370 }
371 dc.hdrflags |= (conversion == CV_FWD) * HF_ENCODE;
372
373 if ((xres > 0) & (yres > 0)) {
374 dc.hdrflags &= ~HF_RESIN;
375 dc.res.rt = PIXSTANDARD;
376 dc.res.xr = xres;
377 dc.res.yr = yres;
378 } else if ((dc.hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESOUT) {
379 fputs(progname, stderr);
380 fputs(": unknown resolution for output\n", stderr);
381 return 1;
382 }
383 if (bypixel) {
384 if (conversion == CV_FWD) {
385 fputs(progname, stderr);
386 fputs(": -i only supported with -r or -p option\n",
387 stderr);
388 usage_exit(1);
389 }
390 if (a >= argc) {
391 fputs(progname, stderr);
392 fputs(": -i option requires input file\n", stderr);
393 usage_exit(1);
394 }
395 if (!(dc.hdrflags & HF_RESIN)) {
396 fputs(progname, stderr);
397 fputs(": -i option requires input resolution\n", stderr);
398 usage_exit(1);
399 }
400 dc.hdrflags &= ~HF_RESOUT;
401 }
402 if (a < argc-2) {
403 fputs(progname, stderr);
404 fputs(": too many file arguments\n", stderr);
405 usage_exit(1);
406 }
407 if (a < argc && !(dc.finp = fopen(dc.inpname=argv[a], "r"))) {
408 fputs(dc.inpname, stderr);
409 fputs(": cannot open for reading\n", stderr);
410 return 1;
411 }
412 if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
413 fputs(argv[a+1], stderr);
414 fputs(": cannot open for writing\n", stderr);
415 return 1;
416 }
417 SET_FILE_BINARY(dc.finp); /* starting assumption */
418 SET_FILE_BINARY(stdout);
419 #ifdef getc_unlocked /* avoid stupid semaphores */
420 flockfile(dc.finp);
421 flockfile(stdout);
422 #endif
423 /* read/copy header */
424 if (!process_dc_header(&dc, a, argv))
425 return 1;
426
427 if ((conversion != CV_FWD) & (dc.format == 'a'))
428 SET_FILE_TEXT(stdout);
429 /* process data */
430 switch (conversion) {
431 case CV_FWD: /* distance -> depth code */
432 if (!strcmp(dc.depth_unit, "1")) {
433 fputs(progname, stderr);
434 fputs(": warning - using reference depth of 1.0\n",
435 stderr);
436 }
437 if (!encode_depths(&dc))
438 return 1;
439 break;
440 case CV_REV: /* depth code -> distance */
441 if (!(bypixel ? pixel_depths(&dc, unbuffered) :
442 decode_depths(&dc)))
443 return 1;
444 break;
445 case CV_PTS: /* depth code -> world points */
446 if (!(bypixel ? pixel_points(&dc, unbuffered) :
447 decode_points(&dc)))
448 return 1;
449 break;
450 }
451 if (fflush(stdout) == EOF) {
452 fputs(progname, stderr);
453 fputs(": error writing output\n", stderr);
454 return 1;
455 }
456 return 0;
457 }