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, 9 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.11 static const char RCSid[] = "$Id: rcode_depth.c,v 2.10 2020/02/12 01:13:01 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.10 if (!strcmp(dcp->inpfmt, "ascii"))
49 greg 2.1 dcp->format = 'a';
50 greg 2.10 else if (!strcmp(dcp->inpfmt, "float"))
51 greg 2.1 dcp->format = 'f';
52 greg 2.10 else if (!strcmp(dcp->inpfmt, "double"))
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.11 if (dcp->format == 'a')
63     SET_FILE_TEXT(dcp->finp);
64 greg 2.3
65 greg 2.1 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 greg 2.6 if (dcp->swapped)
77     swap32((char *)&f, 1);
78 greg 2.1 d = f;
79     break;
80     case 'd':
81     ok = (getbinary(&d, sizeof(d), 1, dcp->finp) == 1);
82 greg 2.6 if (dcp->swapped)
83     swap64((char *)&d, 1);
84 greg 2.1 break;
85     }
86     if (!ok)
87     break;
88 greg 2.3
89 greg 2.1 putint(depth2code(d, dcp->refdepth), 2, stdout);
90 greg 2.3
91 greg 2.1 } 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 greg 2.3 /* Convert and output the given depth to stdout */
103 greg 2.1 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 greg 2.3 long nexpected = (long)dcp->res.xr * dcp->res.yr;
128 greg 2.1
129     if (!check_decode_depths(dcp))
130     return 0;
131    
132     do {
133 greg 2.3 double d = decode_depth_next(dcp);
134 greg 2.1 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 greg 2.3
166 greg 2.1 loc2pix(xy, &dcp->res,
167     (xy[0]+.5)/dcp->res.xr, (xy[1]+.5)/dcp->res.yr);
168 greg 2.3
169 greg 2.1 d = decode_depth_pix(dcp, xy[0], xy[1]);
170     if (d < -FTINY)
171     return 0;
172 greg 2.3
173 greg 2.1 output_depth(dcp, d);
174 greg 2.3
175 greg 2.1 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 greg 2.3 /* Output the given world position to stdout */
191 greg 2.1 static void
192     output_worldpos(DEPTHCODEC *dcp, FVECT wpos)
193     {
194     switch (dcp->format) {
195     case 'a':
196 greg 2.3 printf("%.5e %.5e %.5e\n", wpos[0], wpos[1], wpos[2]);
197 greg 2.1 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 greg 2.11
262 greg 2.1 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 greg 2.7 int xres=0, yres=0;
287 greg 2.1 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 greg 2.7 case 'x':
361     xres = atoi(argv[++a]);
362     break;
363     case 'y':
364     yres = atoi(argv[++a]);
365     break;
366 greg 2.1 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 greg 2.7 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 greg 2.1 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 greg 2.4 dc.hdrflags &= ~HF_RESOUT;
405 greg 2.1 }
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 greg 2.11 SET_FILE_BINARY(dc.finp); /* starting assumption */
422     SET_FILE_BINARY(stdout);
423 greg 2.1 #ifdef getc_unlocked /* avoid stupid semaphores */
424     flockfile(dc.finp);
425     flockfile(stdout);
426     #endif
427     /* read/copy header */
428 greg 2.2 if (!process_dc_header(&dc, a, argv))
429 greg 2.1 return 1;
430 greg 2.11
431     if ((conversion != CV_FWD) & (dc.format == 'a'))
432     SET_FILE_TEXT(stdout);
433 greg 2.1 /* process data */
434     switch (conversion) {
435     case CV_FWD: /* distance -> depth code */
436 greg 2.9 if (!strcmp(dc.depth_unit, "1")) {
437     fputs(progname, stderr);
438     fputs(": warning - using reference depth of 1.0\n",
439     stderr);
440     }
441 greg 2.1 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     }