ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/depthcodec.c
Revision: 2.1
Committed: Thu Jul 18 18:51:56 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Created rcode_depth utility to encode/decode 16-bit depth maps

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * Routines to encode/decoded 16-bit depths
6     */
7    
8     #include "copyright.h"
9    
10     #include <stdlib.h>
11     #include <string.h>
12     #include <math.h>
13     #include <ctype.h>
14     #include "rtio.h"
15     #include "fvect.h"
16     #include "depthcodec.h"
17    
18     char *progname = "depth_codec";
19    
20    
21     /* Encode depth as 16-bit signed integer */
22     short
23     depth2code(double d, double dref)
24     {
25     if (d <= .0)
26     return -32768;
27    
28     if (d > dref)
29     return 32767 - 32768*dref/d;
30    
31     return 32767*d/dref - 32768;
32     }
33    
34    
35     /* Decode depth from 16-bit signed integer */
36     double
37     code2depth(short c, double dref)
38     {
39     if (c < 0)
40     return dref*(32768 + c)*(1./32767.);
41    
42     if (c == 32767)
43     return FHUGE;
44    
45     return dref*32768./(32767 - c);
46     }
47    
48    
49     /* Set codec defaults */
50     void
51     set_dc_defaults(DEPTHCODEC *dcp)
52     {
53     memset(dcp, 0, sizeof(DEPTHCODEC));
54     dcp->finp = stdin;
55     dcp->inpname = "<stdin>";
56     dcp->format = 'a';
57     dcp->refdepth = 1.;
58     dcp->depth_unit[0] = '1';
59     dcp->vw = stdview;
60     dcp->res.rt = PIXSTANDARD;
61     }
62    
63    
64     /* process header line */
65     static int
66     headline(char *s, void *p)
67     {
68     DEPTHCODEC *dcp = (DEPTHCODEC *)p;
69    
70     if (formatval(dcp->inpfmt, s)) /* don't pass format */
71     return 0;
72     /* check for reference depth */
73     if (!strncmp(s, DEPTHSTR, LDEPTHSTR)) {
74     char *cp;
75     strlcpy(dcp->depth_unit, s+LDEPTHSTR, sizeof(dcp->depth_unit));
76     cp = dcp->depth_unit;
77     while (*cp) cp++;
78     while (cp > dcp->depth_unit && isspace(cp[-1])) cp--;
79     *cp = '\0';
80     dcp->refdepth = atof(dcp->depth_unit);
81     if (dcp->refdepth <= .0) {
82     fputs(dcp->inpname, stderr);
83     fputs(": bad reference depth in input header\n", stderr);
84     return -1;
85     }
86     } else if (isview(s)) /* get view params */
87     dcp->gotview += (sscanview(&dcp->vw, s) > 0);
88     if (dcp->hdrflags & HF_HEADOUT)
89     fputs(s, stdout); /* copy to standard output */
90     return 1;
91     }
92    
93    
94     /* Load/copy header */
95     int
96     process_dc_header(DEPTHCODEC *dcp, int ac, char *av[])
97     {
98     if (dcp->hdrflags & HF_HEADIN &&
99     getheader(dcp->finp, headline, dcp) < 0) {
100     fputs(dcp->inpname, stderr);
101     fputs(": bad header\n", stderr);
102     return 1;
103     }
104     if (dcp->hdrflags & HF_HEADOUT) { /* finish header */
105     if (!(dcp->hdrflags & HF_HEADIN))
106     newheader("RADIANCE", stdout);
107     if (ac > 0)
108     printargs(ac, av, stdout);
109     if (dcp->hdrflags & HF_ENCODE) {
110     fputs(DEPTHSTR, stdout);
111     fputs(dcp->depth_unit, stdout);
112     fputc('\n', stdout);
113     fputformat(DEPTH16FMT, stdout);
114     } else
115     switch (dcp->format) {
116     case 'a':
117     fputformat("ascii", stdout);
118     break;
119     case 'f':
120     fputformat("float", stdout);
121     break;
122     case 'd':
123     fputformat("double", stdout);
124     break;
125     }
126     fputc('\n', stdout);
127     }
128     /* get/put resolution string */
129     if (dcp->hdrflags & HF_RESIN && !fgetsresolu(&dcp->res, dcp->finp)) {
130     fputs(dcp->inpname, stderr);
131     fputs(": bad resolution string\n", stderr);
132     return 1;
133     }
134     if (dcp->hdrflags & HF_RESOUT)
135     fputsresolu(&dcp->res, stdout);
136    
137     dcp->dstart = dcp->curpos = ftell(dcp->finp);
138     return 1;
139     }
140    
141    
142     /* Check that we have what we need to decode depths */
143     int
144     check_decode_depths(DEPTHCODEC *dcp)
145     {
146     if (dcp->hdrflags & HF_ENCODE) {
147     fputs(progname, stderr);
148     fputs(": wrong header mode for decode\n", stderr);
149     return 0;
150     }
151     if (dcp->inpfmt[0] && strcmp(dcp->inpfmt, DEPTH16FMT)) {
152     fputs(dcp->inpname, stderr);
153     fputs(": unexpected input format: ", stderr);
154     fputs(dcp->inpfmt, stderr);
155     fputc('\n', stderr);
156     return 0;
157     }
158     return 1;
159     }
160    
161    
162     /* Check that we have what we need to decode world positions */
163     int
164     check_decode_worldpos(DEPTHCODEC *dcp)
165     {
166     char *err;
167    
168     if (!check_decode_depths(dcp))
169     return 0;
170     if ((dcp->res.xr <= 0) | (dcp->res.yr <= 0)) {
171     fputs(progname, stderr);
172     fputs(": missing image resolution\n", stderr);
173     return 0;
174     }
175     if (!dcp->gotview) {
176     fputs(dcp->inpname, stderr);
177     fputs(": missing view\n", stderr);
178     return 0;
179     }
180     if ((err = setview(&dcp->vw)) != NULL) {
181     fputs(dcp->inpname, stderr);
182     fputs(": input view error: ", stderr);
183     fputs(err, stderr);
184     fputc('\n', stderr);
185     return 0;
186     }
187     return 1;
188     }
189    
190    
191     /* Decode next depth pixel */
192     double
193     decode_depth_next(DEPTHCODEC *dcp)
194     {
195     int c = getint(2, dcp->finp);
196    
197     if (c == EOF && feof(dcp->finp))
198     return -1.;
199    
200     dcp->curpos += 2;
201    
202     return code2depth(c, dcp->refdepth);
203     }
204    
205    
206     /* Compute world position from depth */
207     int
208     compute_worldpos(FVECT wpos, DEPTHCODEC *dcp, int x, int y, double d)
209     {
210     RREAL loc[2];
211     FVECT rdir;
212    
213     pix2loc(loc, &dcp->res, x, y);
214    
215     if (viewray(wpos, rdir, &dcp->vw, loc[0], loc[1]) < -FTINY) {
216     VCOPY(wpos, dcp->vw.vp);
217     return 0;
218     }
219     VSUM(wpos, wpos, rdir, d);
220     return 1;
221     }
222    
223    
224     /* Decode the next world position */
225     int
226     decode_worldpos_next(FVECT wpos, DEPTHCODEC *dcp)
227     {
228     const long n = (dcp->curpos - dcp->dstart)>>1;
229     int x, y;
230     double d;
231    
232     d = decode_depth_next(dcp);
233     if (d < -FTINY)
234     return -1;
235    
236     x = scanlen(&dcp->res);
237     y = n / x;
238     x = n - (long)y*x;
239    
240     return compute_worldpos(wpos, dcp, x, y, d);
241     }
242    
243    
244     /* Seek to the indicated pixel position */
245     int
246     seek_dc_pix(DEPTHCODEC *dcp, int x, int y)
247     {
248     long seekpos;
249    
250     if ((dcp->res.xr <= 0) | (dcp->res.yr <= 0)) {
251     fputs(progname, stderr);
252     fputs(": need image resolution to seek\n", stderr);
253     return -1;
254     }
255     if ((x < 0) | (y < 0) ||
256     (x >= scanlen(&dcp->res)) | (y >= numscans(&dcp->res))) {
257     fputs(dcp->inpname, stderr);
258     fputs(": warning - pixel index off image\n", stderr);
259     return 0;
260     }
261     seekpos = dcp->dstart + 2*((long)y*scanlen(&dcp->res) + x);
262     if (seekpos != dcp->curpos &&
263     fseek(dcp->finp, seekpos, SEEK_SET) == EOF) {
264     fputs(dcp->inpname, stderr);
265     fputs(": seek error\n", stderr);
266     return -1;
267     }
268     dcp->curpos = seekpos;
269     return 1;
270     }
271    
272    
273     /* Read and decode depth for the given pixel */
274     double
275     decode_depth_pix(DEPTHCODEC *dcp, int x, int y)
276     {
277     int rval = seek_dc_pix(dcp, x, y);
278    
279     if (rval < 0)
280     return -1.;
281     if (!rval)
282     return .0;
283    
284     return decode_depth_next(dcp);
285     }
286    
287    
288     /* Read and decode the world position at the given pixel */
289     int
290     get_worldpos_pix(FVECT wpos, DEPTHCODEC *dcp, int x, int y)
291     {
292     double d = decode_depth_pix(dcp, x, y);
293    
294     if (d < -FTINY)
295     return -1;
296    
297     return compute_worldpos(wpos, dcp, x, y, d);
298     }