ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_depth.c
Revision: 2.9
Committed: Tue Feb 11 18:15:23 2020 UTC (4 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +6 -1 lines
Log Message:
Added warning about default reference depth on forward conversion

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.9 static const char RCSid[] = "$Id: rcode_depth.c,v 2.8 2019/11/13 18:20:47 greg Exp $";
3 greg 2.1 #endif
4     /*
5 greg 2.3 * Encode and decode depth map using 16-bit integers
6 greg 2.1 */
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 greg 2.3 char *progname; /* set in main() */
19    
20 greg 2.1 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 greg 2.8 " [-d ref_depth/unit][-h[io]][-H[io]][-f[afd]][-x xr -y yr] [input [output.dpt]]\n",
31 greg 2.1 stderr);
32     fputs(" Or: ", stderr);
33     fputs(progname, stderr);
34     fputs(
35 greg 2.4 " {-r|-p} [-i][-u][-h[io]][-H[io]][-f[afd]] [input.dpt [output]]\n",
36 greg 2.1 stderr);
37     exit(code);
38     }
39    
40    
41     /* Encode depths from input stream */
42     static int
43     encode_depths(DEPTHCODEC *dcp)
44     {
45 greg 2.3 long nexpected = (long)dcp->res.xr * dcp->res.yr;
46 greg 2.1
47     if (dcp->inpfmt[0]) {
48 greg 2.5 if (strstr(dcp->inpfmt, "ascii") != NULL)
49 greg 2.1 dcp->format = 'a';
50 greg 2.5 else if (strstr(dcp->inpfmt, "float") != NULL)
51 greg 2.1 dcp->format = 'f';
52 greg 2.5 else if (strstr(dcp->inpfmt, "double") != NULL)
53 greg 2.1 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 greg 2.3
63 greg 2.1 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 greg 2.6 if (dcp->swapped)
75     swap32((char *)&f, 1);
76 greg 2.1 d = f;
77     break;
78     case 'd':
79     ok = (getbinary(&d, sizeof(d), 1, dcp->finp) == 1);
80 greg 2.6 if (dcp->swapped)
81     swap64((char *)&d, 1);
82 greg 2.1 break;
83     }
84     if (!ok)
85     break;
86 greg 2.3
87 greg 2.1 putint(depth2code(d, dcp->refdepth), 2, stdout);
88 greg 2.3
89 greg 2.1 } 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 greg 2.3 /* Convert and output the given depth to stdout */
101 greg 2.1 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 greg 2.3 long nexpected = (long)dcp->res.xr * dcp->res.yr;
126 greg 2.1
127     if (!check_decode_depths(dcp))
128     return 0;
129    
130     do {
131 greg 2.3 double d = decode_depth_next(dcp);
132 greg 2.1 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 greg 2.3
164 greg 2.1 loc2pix(xy, &dcp->res,
165     (xy[0]+.5)/dcp->res.xr, (xy[1]+.5)/dcp->res.yr);
166 greg 2.3
167 greg 2.1 d = decode_depth_pix(dcp, xy[0], xy[1]);
168     if (d < -FTINY)
169     return 0;
170 greg 2.3
171 greg 2.1 output_depth(dcp, d);
172 greg 2.3
173 greg 2.1 if (unbuf && fflush(stdout) == EOF) {
174     fputs(progname, stderr);
175     fputs(": write error on output\n", stderr);
176     return 0;
177     }
178     }
179     if (!feof(stdin)) {
180     fputs(progname, stderr);
181     fputs(": non-integer as pixel index\n", stderr);
182     return 0;
183     }
184     return 1;
185     }
186    
187    
188 greg 2.3 /* Output the given world position to stdout */
189 greg 2.1 static void
190     output_worldpos(DEPTHCODEC *dcp, FVECT wpos)
191     {
192     switch (dcp->format) {
193     case 'a':
194 greg 2.3 printf("%.5e %.5e %.5e\n", wpos[0], wpos[1], wpos[2]);
195 greg 2.1 break;
196     #ifdef SMLFLT
197     case 'f':
198     putbinary(wpos, sizeof(*wpos), 3, stdout);
199     break;
200     case 'd': {
201     double wpd[3];
202     VCOPY(wpd, wpos);
203     putbinary(wpd, sizeof(*wpd), 3, stdout);
204     }
205     break;
206     #else
207     case 'f': {
208     float wpf[3];
209     VCOPY(wpf, wpos);
210     putbinary(wpf, sizeof(*wpf), 3, stdout);
211     }
212     break;
213     case 'd':
214     putbinary(wpos, sizeof(*wpos), 3, stdout);
215     break;
216     #endif
217     }
218     }
219    
220    
221     /* Decode world points from input stream */
222     static int
223     decode_points(DEPTHCODEC *dcp)
224     {
225     long n = (long)dcp->res.xr * dcp->res.yr;
226    
227     if (!check_decode_worldpos(dcp))
228     return 0;
229    
230     while (n-- > 0) {
231     FVECT wpos;
232     if (decode_worldpos_next(wpos, dcp) < 0) {
233     if (feof(dcp->finp)) {
234     fputs(dcp->inpname, stderr);
235     fputs(": unexpected EOF\n", stderr);
236     }
237     return 0;
238     }
239     output_worldpos(dcp, wpos);
240     }
241     return 1;
242     }
243    
244    
245     /* Decode world points at particular pixels given on standard input */
246     static int
247     pixel_points(DEPTHCODEC *dcp, int unbuf)
248     {
249     int xy[2];
250     FVECT wpos;
251    
252     if (dcp->finp == stdin) {
253     fputs(progname, stderr);
254     fputs(": <stdin> used for encoded depths\n", stderr);
255     return 0;
256     }
257     if (!check_decode_worldpos(dcp))
258     return 0;
259    
260     while (scanf("%d %d", &xy[0], &xy[1]) == 2) {
261     loc2pix(xy, &dcp->res,
262     (xy[0]+.5)/dcp->res.xr, (xy[1]+.5)/dcp->res.yr);
263     if (get_worldpos_pix(wpos, dcp, xy[0], xy[1]) < 0)
264     return 0;
265     output_worldpos(dcp, wpos);
266     if (unbuf && fflush(stdout) == EOF) {
267     fputs(progname, stderr);
268     fputs(": write error on output\n", stderr);
269     return 0;
270     }
271     }
272     if (!feof(stdin)) {
273     fputs(progname, stderr);
274     fputs(": non-integer as pixel index\n", stderr);
275     return 0;
276     }
277     return 1;
278     }
279    
280    
281     int
282     main(int argc, char *argv[])
283     {
284 greg 2.7 int xres=0, yres=0;
285 greg 2.1 int conversion = CV_FWD;
286     int bypixel = 0;
287     int unbuffered = 0;
288     DEPTHCODEC dc;
289     int a;
290    
291     progname = argv[0];
292     set_dc_defaults(&dc);
293     dc.hdrflags = HF_ALL;
294     for (a = 1; a < argc && argv[a][0] == '-'; a++)
295     switch (argv[a][1]) {
296     case 'd':
297     strlcpy(dc.depth_unit, argv[++a], sizeof(dc.depth_unit));
298     dc.refdepth = atof(dc.depth_unit);
299     if (dc.refdepth <= .0) {
300     fputs(progname, stderr);
301     fputs(": illegal -d reference depth\n", stderr);
302     return 1;
303     }
304     break;
305     case 'r':
306     conversion = CV_REV;
307     break;
308     case 'p':
309     conversion = CV_PTS;
310     break;
311     case 'f':
312     switch (argv[a][2]) {
313     case 'f':
314     case 'd':
315     case 'a':
316     dc.format = argv[a][2];
317     break;
318     default:
319     fputs(progname, stderr);
320     fputs(": unsupported -f? format\n", stderr);
321     usage_exit(1);
322     }
323     break;
324     case 'h':
325     switch (argv[a][2]) {
326     case '\0':
327     dc.hdrflags &= ~(HF_HEADIN|HF_HEADOUT);
328     break;
329     case 'i':
330     case 'I':
331     dc.hdrflags &= ~HF_HEADIN;
332     break;
333     case 'o':
334     case 'O':
335     dc.hdrflags &= ~HF_HEADOUT;
336     break;
337     default:
338     usage_exit(1);
339     }
340     break;
341     case 'H':
342     switch (argv[a][2]) {
343     case '\0':
344     dc.hdrflags &= ~(HF_RESIN|HF_RESOUT);
345     break;
346     case 'i':
347     case 'I':
348     dc.hdrflags &= ~HF_RESIN;
349     break;
350     case 'o':
351     case 'O':
352     dc.hdrflags &= ~HF_RESOUT;
353     break;
354     default:
355     usage_exit(1);
356     }
357     break;
358 greg 2.7 case 'x':
359     xres = atoi(argv[++a]);
360     break;
361     case 'y':
362     yres = atoi(argv[++a]);
363     break;
364 greg 2.1 case 'i':
365     bypixel++;
366     break;
367     case 'u':
368     unbuffered++;
369     break;
370     default:
371     usage_exit(1);
372     }
373     dc.hdrflags |= (conversion == CV_FWD) * HF_ENCODE;
374    
375 greg 2.7 if ((xres > 0) & (yres > 0)) {
376     dc.hdrflags &= ~HF_RESIN;
377     dc.res.rt = PIXSTANDARD;
378     dc.res.xr = xres;
379     dc.res.yr = yres;
380     } else if ((dc.hdrflags & (HF_RESIN|HF_RESOUT)) == HF_RESOUT) {
381 greg 2.1 fputs(progname, stderr);
382     fputs(": unknown resolution for output\n", stderr);
383     return 1;
384     }
385     if (bypixel) {
386     if (conversion == CV_FWD) {
387     fputs(progname, stderr);
388     fputs(": -i only supported with -r or -p option\n",
389     stderr);
390     usage_exit(1);
391     }
392     if (a >= argc) {
393     fputs(progname, stderr);
394     fputs(": -i option requires input file\n", stderr);
395     usage_exit(1);
396     }
397     if (!(dc.hdrflags & HF_RESIN)) {
398     fputs(progname, stderr);
399     fputs(": -i option requires input resolution\n", stderr);
400     usage_exit(1);
401     }
402 greg 2.4 dc.hdrflags &= ~HF_RESOUT;
403 greg 2.1 }
404     if (a < argc-2) {
405     fputs(progname, stderr);
406     fputs(": too many file arguments\n", stderr);
407     usage_exit(1);
408     }
409     if (a < argc && !(dc.finp = fopen(dc.inpname=argv[a], "r"))) {
410     fputs(dc.inpname, stderr);
411     fputs(": cannot open for reading\n", stderr);
412     return 1;
413     }
414     if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
415     fputs(argv[a+1], stderr);
416     fputs(": cannot open for writing\n", stderr);
417     return 1;
418     }
419     SET_FILE_BINARY(dc.finp);
420 greg 2.3 if ((conversion != CV_FWD) | (dc.format != 'a'))
421     SET_FILE_BINARY(stdout);
422 greg 2.1 #ifdef getc_unlocked /* avoid stupid semaphores */
423     flockfile(dc.finp);
424     flockfile(stdout);
425     #endif
426     /* read/copy header */
427 greg 2.2 if (!process_dc_header(&dc, a, argv))
428 greg 2.1 return 1;
429     /* process data */
430     switch (conversion) {
431     case CV_FWD: /* distance -> depth code */
432 greg 2.9 if (!strcmp(dc.depth_unit, "1")) {
433     fputs(progname, stderr);
434     fputs(": warning - using reference depth of 1.0\n",
435     stderr);
436     }
437 greg 2.1 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     }