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 (21 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.11: +5 -9 lines
Log Message:
fix(rcode_depth): Pixels with -i option were off by 1

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.12 static const char RCSid[] = "$Id: rcode_depth.c,v 2.11 2020/07/20 15:53:30 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.12 loc2pix(xy, &dcp->res, xy[0]/(double)dcp->res.xr,
166     xy[1]/(double)dcp->res.yr);
167 greg 2.1 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 greg 2.3 /* Output the given world position to stdout */
187 greg 2.1 static void
188     output_worldpos(DEPTHCODEC *dcp, FVECT wpos)
189     {
190     switch (dcp->format) {
191     case 'a':
192 greg 2.3 printf("%.5e %.5e %.5e\n", wpos[0], wpos[1], wpos[2]);
193 greg 2.1 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 greg 2.11
258 greg 2.1 while (scanf("%d %d", &xy[0], &xy[1]) == 2) {
259 greg 2.12 loc2pix(xy, &dcp->res, xy[0]/(double)dcp->res.xr,
260     xy[1]/(double)dcp->res.yr);
261 greg 2.1 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 greg 2.7 int xres=0, yres=0;
283 greg 2.1 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 greg 2.7 case 'x':
357     xres = atoi(argv[++a]);
358     break;
359     case 'y':
360     yres = atoi(argv[++a]);
361     break;
362 greg 2.1 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 greg 2.7 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 greg 2.1 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 greg 2.4 dc.hdrflags &= ~HF_RESOUT;
401 greg 2.1 }
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 greg 2.11 SET_FILE_BINARY(dc.finp); /* starting assumption */
418     SET_FILE_BINARY(stdout);
419 greg 2.1 #ifdef getc_unlocked /* avoid stupid semaphores */
420     flockfile(dc.finp);
421     flockfile(stdout);
422     #endif
423     /* read/copy header */
424 greg 2.2 if (!process_dc_header(&dc, a, argv))
425 greg 2.1 return 1;
426 greg 2.11
427     if ((conversion != CV_FWD) & (dc.format == 'a'))
428     SET_FILE_TEXT(stdout);
429 greg 2.1 /* 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     }